diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 41e2a78e3..782950a42 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -261,7 +261,7 @@ jobs: echo "BOX64_COMPILER=loongarch64-linux-gnu-gcc" >> $GITHUB_ENV sudo apt-get -y install git cmake make python3 libzydis-dev elif [[ ${{ matrix.platform }} == 'PPC64LE' ]]; then - echo BOX64_PLATFORM_MARCRO="-DPPC64LE=ON" >> $GITHUB_ENV + echo BOX64_PLATFORM_MARCRO="-DPPC64LE=ON -DBAD_SIGNAL=ON" >> $GITHUB_ENV echo "BOX64_COMPILER=powerpc64le-linux-gnu-gcc" >> $GITHUB_ENV sudo apt-get -y install git gcc-powerpc64le-linux-gnu cmake make python3 libzydis-dev else diff --git a/AGENTS.md b/AGENTS.md index 2a633ad04..ada114da9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,7 @@ These use cases are **permitted** when making a contribution with the help of AI - Formatting code for consistency and readability (but do not overload code with comments) - Completing code segments based on established patterns - Drafting documentation for project components with which the contributor is already familiar - - Writting Wrappers Callback handling and/or wrappers structures conversion when needed + - Writing Wrappers Callback handling and/or wrappers structures conversion when needed AI-generated code that has undergone extensive human editing may be accepted, provided you (1) fully understand the AI's initial output, (2) can debug any issues independently (with or without further AI assistance), and (3) are prepared to discuss it directly with human reviewers. diff --git a/CMakeLists.txt b/CMakeLists.txt index 4098f33e2..c4f82ab5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,8 +265,9 @@ elseif(LARCH64) set(ASMFLAGS -pipe -march=loongarch64) elseif(RV64) add_definitions(-DRV64) - set(CFLAGS -pipe -march=rv64gc) + set(CFLAGS -pipe -march=rv64gc -fno-tree-vectorize) set(ASMFLAGS -pipe -march=rv64gc) + add_compile_options(-fno-tree-vectorize) elseif(PPC64LE) add_definitions(-DPPC64LE) set(CFLAGS -pipe -mcpu=power9) @@ -384,6 +385,8 @@ endif() set(BOX64_ROOT ${CMAKE_SOURCE_DIR}) add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden) +add_definitions(-D_GNU_SOURCE=1) +add_definitions(-D_FILE_OFFSET_BITS=64) if(USE_CCACHE) find_program(CCACHE_FOUND ccache) @@ -1103,6 +1106,7 @@ if(RV64_DYNAREC) "${BOX64_ROOT}/src/dynarec/rv64/rv64_printer.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_jmpnext.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_consts.c" + "${BOX64_ROOT}/src/dynarec/rv64/rv64_mov_imm.c" "${BOX64_ROOT}/src/dynarec/rv64/updateflags_rv64.c" ) set(DYNAREC_ASM @@ -1675,6 +1679,7 @@ if(ARM64EC) SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wine/box64ec" CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/wine/toolchain_mingw_arm64ec.cmake + -DDYNAREC_PASS_STR=${DYNAREC_PASS_STR} -DINTERPRETER_STR=${INTERPRETER_STR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} INSTALL_COMMAND "" diff --git a/README.md b/README.md index 7e2417d14..6e219facb 100644 --- a/README.md +++ b/README.md @@ -58,14 +58,14 @@ Box64 requires 64-bit libraries on the host system, as it directly translates x8 1. Box32 is still experimental, but it's pretty stable now and can be used. 2. Some shell scripts (such as the GOG game installer) may rely on `uname -m` to determine the current architecture. Please run them as `box64 script.sh` to allow Box64 to take over. -Note that DynaCache is now enabled by default (with compression). This will creates files in `~/.cache/box64` to save generated code for executed binaries and libraries, so launch time can be greatly reduced on second run. The files are compressed and will take up to 2Gb by default. You can disable DynaCache writting, by switching it to a Read-only mode by creating (or modifying) `~/.box64rc` and writting there +Note that DynaCache is now enabled by default (with compression). This will creates files in `~/.cache/box64` to save generated code for executed binaries and libraries, so launch time can be greatly reduced on second run. The files are compressed and will take up to 2Gb by default. You can disable DynaCache writing, by switching it to a Read-only mode by creating (or modifying) `~/.box64rc` and writing there ```ini [*] BOX64_DYNACACHE=2 ``` -(or 0 to completly disabled it). Please refer to [Usage Documentation](docs/USAGE.md) for more details on how to configure Box64. +(or 0 to completely disabled it). Please refer to [Usage Documentation](docs/USAGE.md) for more details on how to configure Box64. --- diff --git a/configurator/model.py b/configurator/model.py index 2c92583da..cf6870740 100644 --- a/configurator/model.py +++ b/configurator/model.py @@ -103,6 +103,7 @@ class ValueState: ("BOX64_DYNAREC_BIGBLOCK", "0"), ("BOX64_DYNAREC_SAFEFLAGS", "2"), ("BOX64_DYNAREC_STRONGMEM", "2"), + ("BOX64_DYNAREC_CALLRET", "3"), ), "safe": ( ("BOX64_DYNAREC_BIGBLOCK", "0"), diff --git a/debian/changelog b/debian/changelog index a3101c7b3..4e3406515 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,178 +1,178 @@ box64 (0.4.4) unstable; urgency=low -This version adds a lot of refactor and speed improvements to the LoongArch backend, so more opcodes on the RISC-V backend, and many QoL new features! - => A new box64-configurator is now present (a python app) to help managing custom RCFILE profiles. It is available in both english and chinese. - => DynaCache is now enabled by default. It will compress the files and use up to 2GB of disk space. - => You can use box64-configurator on the special `[*]` profile to change default values - => More improvements on emulation accuracy that help running more DRM'd games + * This version adds a lot of refactor and speed improvements to the LoongArch backend, so more opcodes on the RISC-V backend, and many QoL new features! + * => A new box64-configurator is now present (a python app) to help managing custom RCFILE profiles. It is available in both english and chinese. + * => DynaCache is now enabled by default. It will compress the files and use up to 2GB of disk space. + * => You can use box64-configurator on the special `[*]` profile to change default values + * => More improvements on emulation accuracy that help running more DRM'd games --- Sebastien Chevalier Mon, 2 Aug 2026 10:30:33 -0100 + -- Sebastien Chevalier Mon, 2 Aug 2026 10:30:33 -0100 box64 (0.4.2) unstable; urgency=low -This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning. - => Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work. - => Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility. - => Support for SteamRT3 & new Proton 11 - => New PCC64LE in the work. Not finished, but should be usable already (but the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm). Note that main Box64 mainteners don't have access to relevent hardware, so support will be limited. + * This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning. + * => Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work. + * => Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility. + * => Support for SteamRT3 & new Proton 11 + * => New PCC64LE in the work. Not finished, but should be usable already (but the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm). Note that main Box64 mainteners don't have access to relevent hardware, so support will be limited. --- Sebastien Chevalier Mon, 20 Apr 2026 10:30:33 -0100 + -- Sebastien Chevalier Mon, 20 Apr 2026 10:30:33 -0100 box64 (0.4.0) unstable; urgency=low -This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster. - => Improved compatibility accross all architecture, allowing more DRM protected game to run - => the prefix refactor helped removed lots of redundant source file, simplifying maintenance - => BOX32 is getting more and more stable, even if still not 100% ok. But Steam is more stable than before, runs on all architecture. And some gameoverlay UI works, on OpenGL games. gameoverlay (and fossilize) support for Vulkan is planned for later. + * This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster. + * => Improved compatibility accross all architecture, allowing more DRM protected game to run + * => the prefix refactor helped removed lots of redundant source file, simplifying maintenance + * => BOX32 is getting more and more stable, even if still not 100% ok. But Steam is more stable than before, runs on all architecture. And some gameoverlay UI works, on OpenGL games. gameoverlay (and fossilize) support for Vulkan is planned for later. --- Sebastien Chevalier Mon, 3 Jan 2026 10:30:33 -0100 + -- Sebastien Chevalier Mon, 3 Jan 2026 10:30:33 -0100 box64 (0.3.8) unstable; urgency=low -This version introduce DynaCache, a disk cache for the generated native code. It's not enabled by default for now (but it will use cache file if present by default). It can dramaticaly speedup the load of program (try with linux factorio for example). This version also improve in the volatile metadata handling. There is a massive compatiblity improvment for box32 and on all dynarec in general too. And few more function wrapping... + * This version introduce DynaCache, a disk cache for the generated native code. It's not enabled by default for now (but it will use cache file if present by default). It can dramaticaly speedup the load of program (try with linux factorio for example). This version also improve in the volatile metadata handling. There is a massive compatiblity improvment for box32 and on all dynarec in general too. And few more function wrapping... - => DynaCache for faster loading of program, and avoid runtime hicups - => Batter box32 compatibility (much less "Out of Memory" error) - => Unity3D games on Wayland are working now - => Volatile Metadata fully supported and handled, making games like Starfield to just work. - => More work on AVX support for RV64 & LA64. LA64 almost there, while RV64 has Scalar only support (no hardware vector support yet for AVX) + * => DynaCache for faster loading of program, and avoid runtime hicups + * => Batter box32 compatibility (much less "Out of Memory" error) + * => Unity3D games on Wayland are working now + * => Volatile Metadata fully supported and handled, making games like Starfield to just work. + * => More work on AVX support for RV64 & LA64. LA64 almost there, while RV64 has Scalar only support (no hardware vector support yet for AVX) --- Sebastien Chevalier Mon, 10 Oct 2025 10:30:33 -0100 + -- Sebastien Chevalier Mon, 10 Oct 2025 10:30:33 -0100 box64 (0.3.6) unstable; urgency=low -This version introduces wowbox64.dll for Hangover; the ability to use the Volatile Metadata of Windows executables for x64 wine; and some better x87/SSE/AVX handling + * This version introduces wowbox64.dll for Hangover; the ability to use the Volatile Metadata of Windows executables for x64 wine; and some better x87/SSE/AVX handling - => WowBox64 can be built directly from Box64 repo, and can be found in the CI artifacts also - => it also supports a subset of BOX64_XXXX settings, which can be set from command line or via a setting file ".box64rc" in the Wine prefix home - => Volatile Metadata, when present, allows only applying strong memory ordering when needed, as marked by the compiler, giving overall better performances - => The precision control bit of x87 is now handled, allowing some older games to run correctly - => More work has been done in the handling of precise NaN and Round handling in SSE & AVX opcodes + * => WowBox64 can be built directly from Box64 repo, and can be found in the CI artifacts also + * => it also supports a subset of BOX64_XXXX settings, which can be set from command line or via a setting file ".box64rc" in the Wine prefix home + * => Volatile Metadata, when present, allows only applying strong memory ordering when needed, as marked by the compiler, giving overall better performances + * => The precision control bit of x87 is now handled, allowing some older games to run correctly + * => More work has been done in the handling of precise NaN and Round handling in SSE & AVX opcodes --- Sebastien Chevalier Thu, 6 Jun 2025 10:30:33 -0100 + -- Sebastien Chevalier Thu, 6 Jun 2025 10:30:33 -0100 box64 (0.3.4) unstable; urgency=low -* This version is Faster and more compatible -* => The RV64 backend got faster and more stable, with lots of RVV 1.0 / xThreadVector support to emulate SSE/SSE2+ opcode (no AVX yet) -* => On ARM64, Box64 now support more DRM types than before. -* => BOX32 can run steam now. At least on ARM64 backend, it's still not working on RV64 and LA64 for now. -* Please check CHAGELOG.md for more details + * This version is Faster and more compatible + * => The RV64 backend got faster and more stable, with lots of RVV 1.0 / xThreadVector support to emulate SSE/SSE2+ opcode (no AVX yet) + * => On ARM64, Box64 now support more DRM types than before. + * => BOX32 can run steam now. At least on ARM64 backend, it's still not working on RV64 and LA64 for now. + * Please check CHAGELOG.md for more details --- Sebastien Chevalier Thu, 10 Mar 2025 10:30:33 -0100 + -- Sebastien Chevalier Thu, 10 Mar 2025 10:30:33 -0100 box64 (0.3.2) unstable; urgency=low -* Introduced Box32 to run 32bits apps on 64bits OS -* => Box32 is a build option for Box64, and is disabled by default -* => Optionnal binfmt integration available for Box32 -* => Wrapped some basics libs, including graphics and sounds so a few games already works -* => Work In Progress, many issues remain to be fixed, but some Linux games are playable -* Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default -* => Available on the 3 Dynarec backend, with different implementations -* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default -* +> Can lead to large speedup on certain cases -* Improved Strong Memory Model emulation, with better default options and a more efficiant emulation -* Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used! -* Some bugfix and improvment in the Signal handler and internal memory tracking -* Improvment to TRAP signal generation and Handling -* Improved CPUID opcodes again, and the various virtual file in /proc that represent those data -* Improved some x87 operations, like long double handling and infinity comparisons... -* Dynarec: ARM64 fixes to a few opcodes -* Dynarec: RV64 fixes to many opcodes -* Dynarec: LA64 fixes to a few opcodes -* Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes -* Dynarec: Many optimisation on some individual opcodes, an all 3 backends -* WRAPPING: More libs and functions wrapped. Some wrapping fixes too -* WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one -* ElfLoader: Improved object fetching -* New build profile for SD865 and ORYON -* Changed the installation folder of x86 libs to avoid conflict with linux distro -* Added a few syscalls -* Some more Vulkan extensions wrapped -* More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational) - --- Sebastien Chevalier Thu, 6 Dec 2024 10:30:33 -0100 + * Introduced Box32 to run 32bits apps on 64bits OS + * => Box32 is a build option for Box64, and is disabled by default + * => Optionnal binfmt integration available for Box32 + * => Wrapped some basics libs, including graphics and sounds so a few games already works + * => Work In Progress, many issues remain to be fixed, but some Linux games are playable + * Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default + * => Available on the 3 Dynarec backend, with different implementations + * => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default + * +> Can lead to large speedup on certain cases + * Improved Strong Memory Model emulation, with better default options and a more efficiant emulation + * Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used! + * Some bugfix and improvment in the Signal handler and internal memory tracking + * Improvment to TRAP signal generation and Handling + * Improved CPUID opcodes again, and the various virtual file in /proc that represent those data + * Improved some x87 operations, like long double handling and infinity comparisons... + * Dynarec: ARM64 fixes to a few opcodes + * Dynarec: RV64 fixes to many opcodes + * Dynarec: LA64 fixes to a few opcodes + * Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes + * Dynarec: Many optimisation on some individual opcodes, an all 3 backends + * WRAPPING: More libs and functions wrapped. Some wrapping fixes too + * WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one + * ElfLoader: Improved object fetching + * New build profile for SD865 and ORYON + * Changed the installation folder of x86 libs to avoid conflict with linux distro + * Added a few syscalls + * Some more Vulkan extensions wrapped + * More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational) + + -- Sebastien Chevalier Thu, 6 Dec 2024 10:30:33 -0100 box64 (0.3.0) unstable; urgency=low -* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension! -* Introduced BOX64_AVX env. var. to enable/disable AVX extension: -* => BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension -* => BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND -* Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU) -* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default -* Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before) -* Dynarec: Small optim in the emit_pf helper, on all 3 backends -* Dynarec: ARM64 some fixes to a few opcodes -* Dynarec: LA64 many new opcodes added, and fixes. -* Dynarec: RV64 some new opcodes added, many fixes. -* Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation. -* Dynarec: Many small changes and fixes around handling of x87, registers and internal jump. -* WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games -* WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions) -* WRAPPING: Wayland is now supported. Wine-wayland at least works now -* Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games) -* Dynarec: RV64 improved LOCK CMPXCHG handling -* COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable -* Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work -* ElfLoader: Added a new type of relocation - --- Sebastien Chevalier Thu, 9 Jul 2024 10:30:33 -0100 + * AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension! + * Introduced BOX64_AVX env. var. to enable/disable AVX extension: + * => BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension + * => BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND + * Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU) + * => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default + * Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before) + * Dynarec: Small optim in the emit_pf helper, on all 3 backends + * Dynarec: ARM64 some fixes to a few opcodes + * Dynarec: LA64 many new opcodes added, and fixes. + * Dynarec: RV64 some new opcodes added, many fixes. + * Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation. + * Dynarec: Many small changes and fixes around handling of x87, registers and internal jump. + * WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games + * WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions) + * WRAPPING: Wayland is now supported. Wine-wayland at least works now + * Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games) + * Dynarec: RV64 improved LOCK CMPXCHG handling + * COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable + * Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work + * ElfLoader: Added a new type of relocation + + -- Sebastien Chevalier Thu, 9 Jul 2024 10:30:33 -0100 box64 (0.2.8) unstable; urgency=low -* Wrapping: More libs and function wrapping (gtk3, vulkan...) -* Reworked X11 Callback handling, for better stability -* Reworked exit and the load/unload of libs and symbol resolution -* Some more profiles in box64rc -* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile -* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation -* Improved memory tracking and managment. Also introduce BOX64_MMAP32 to force 32bits compatible mmap for external libs (like mesa) -* => Allow Vulkan drvier on Wine/WOW64 games to allocate 32bits compatible memory, allowing dxvk on 32bits. -* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation -* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.) -* => should improve games stability -* Dynarec: ARM64 some opcodes optimisation, especialy shift and rotation ones -* Dynarec: RV64 lots of opcoded added. -* => Some games on linux now have a good speed. Game on Wine are still a bit slow, and dxvk still have issues -* Dynarec: Added Loogarch backend! Note that Loongarch are 16K pagesize platform by default. -* => Linux games are running, and with good speed, especialy on 3A6000 platforms. Games on Wine are not working yet due to 16k pagesize limitation -* Dynarec: Better handling of large block in the dynarec -* Dynarec: Lots of improvments and fixes to BOX86_DYNAREC_CALLRET optimisation. -* => It can be used on more software now, and combine with BOX64_DYNAREC_BOGBLOCKS 2 or 3 can gives some good speed boosts. - --- Sebastien Chevalier Thu, 31 May 2024 17:30:33 -0100 + * Wrapping: More libs and function wrapping (gtk3, vulkan...) + * Reworked X11 Callback handling, for better stability + * Reworked exit and the load/unload of libs and symbol resolution + * Some more profiles in box64rc + * Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile + * Reworked memory managment in the Dynarec, limiting amount of dynamic allocation + * Improved memory tracking and managment. Also introduce BOX64_MMAP32 to force 32bits compatible mmap for external libs (like mesa) + * => Allow Vulkan drvier on Wine/WOW64 games to allocate 32bits compatible memory, allowing dxvk on 32bits. + * Reworked memory managment in the Dynarec, limiting amount of dynamic allocation + * Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.) + * => should improve games stability + * Dynarec: ARM64 some opcodes optimisation, especialy shift and rotation ones + * Dynarec: RV64 lots of opcoded added. + * => Some games on linux now have a good speed. Game on Wine are still a bit slow, and dxvk still have issues + * Dynarec: Added Loogarch backend! Note that Loongarch are 16K pagesize platform by default. + * => Linux games are running, and with good speed, especialy on 3A6000 platforms. Games on Wine are not working yet due to 16k pagesize limitation + * Dynarec: Better handling of large block in the dynarec + * Dynarec: Lots of improvments and fixes to BOX86_DYNAREC_CALLRET optimisation. + * => It can be used on more software now, and combine with BOX64_DYNAREC_BOGBLOCKS 2 or 3 can gives some good speed boosts. + + -- Sebastien Chevalier Thu, 31 May 2024 17:30:33 -0100 box64 (0.2.6) unstable; urgency=low - * X64Libs: Updated libstdc++ & libgcc_s - * X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine) - * Dynarec: More opcodes on ARM64 & RV64 - * Dynarec: Fixed some flags propagation issues inside blocks - * Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level - * Dynarec: ARM64: reworked shift and bit opcodes flags handling - * Dynarec: RV64: Many fixes, making Wow64 apps running - * Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU) - * Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it) - * Dynarec: ARM64: The CALLRET optimisation has been improved and is now default - * CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works - * CPU: Added full support for SSE4.2 - * CPU: Added full support for SHA extension - * ElfLoader: rework how elf memory is handled - * Emulation: Added some more syscalls - * Emulation: Better handling of Signal (also handling SIGMAX correctly) - * Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games) - * Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...) - * Wrapping: Removed faked libunwind wrapping - * Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines - * OS: Added profile to build for Android and Termux. - * OS: New option to use mold for a high speed link - * => More hadware support, more functions wrapped for an improve compatibity - * => More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation - * => Some work also to reduce the memory footprint - --- Sebastien Chevalier Thu, 15 Dec 2023 17:30:33 -0100 + * X64Libs: Updated libstdc++ & libgcc_s + * X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine) + * Dynarec: More opcodes on ARM64 & RV64 + * Dynarec: Fixed some flags propagation issues inside blocks + * Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level + * Dynarec: ARM64: reworked shift and bit opcodes flags handling + * Dynarec: RV64: Many fixes, making Wow64 apps running + * Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU) + * Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it) + * Dynarec: ARM64: The CALLRET optimisation has been improved and is now default + * CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works + * CPU: Added full support for SSE4.2 + * CPU: Added full support for SHA extension + * ElfLoader: rework how elf memory is handled + * Emulation: Added some more syscalls + * Emulation: Better handling of Signal (also handling SIGMAX correctly) + * Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games) + * Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...) + * Wrapping: Removed faked libunwind wrapping + * Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines + * OS: Added profile to build for Android and Termux. + * OS: New option to use mold for a high speed link + * => More hadware support, more functions wrapped for an improve compatibity + * => More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation + * => Some work also to reduce the memory footprint + + -- Sebastien Chevalier Thu, 15 Dec 2023 17:30:33 -0100 box64 (0.2.4) unstable; urgency=low @@ -199,74 +199,74 @@ box64 (0.2.4) unstable; urgency=low * => Dynarec now support RISC-V, large speedup on RISC-V 64, were games are now playable (like Stardew Valley on a Vision Five 2) * => Improved compatibility with more fixes in elf handling, more wrapped libs and functiond, more fixed opcodes and refined profile --- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 + -- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 box64 (0.2.2) unstable; urgency=low - * Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work. - * Added rcfile handling: box64 now read "/etc/box64.box64rc" and "~/.box64rc" and apply per process parameters - * Added BOX64_DYNAREC_CALLRET to optimized CALL/RET opcode using semi-direct native CALL/RET (get more than 10% speedup) - * Added BOX64_DYNAREC_FORWARD to allow bigger Dynarec block to be build (can get more then 30% of Speedup!) - * Improved memory protection tracking and signal handling, again - * Simplified mutex handling (faster, cleaner) - * Reduce memory used by the memory tracking (memory almost divide by 4 is some critical use case) - * Added d3dadaptor9 wrapping - * More wrapped libs (especially on the gtk familly) - * Improved/fixed some Syscall handling - * Refactored Strong Memory Model emulation (faster and more accurate) - * Added some more opcode to ARM64 Dynarec, and fixed some other - * Some fixes to flags handling in the Dynarec on some special cases - * Refactor library loading/unloading, with refcount. - * Some special cases fixes for dlopen (fixes deadcells, maybe others too) - * Improved mmap mapping, espcially with MAP_32BITS flag - * More wrapped functions and syscalls - * Lots of improvment in the Rounding of float & double (Dynarec and Interpreter), and proper handling of denormals when converting to/from 80 bits long double - * Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel) - * More support on the RV64 port - * More support to build under musl environment - --- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 + * Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work. + * Added rcfile handling: box64 now read "/etc/box64.box64rc" and "~/.box64rc" and apply per process parameters + * Added BOX64_DYNAREC_CALLRET to optimized CALL/RET opcode using semi-direct native CALL/RET (get more than 10% speedup) + * Added BOX64_DYNAREC_FORWARD to allow bigger Dynarec block to be build (can get more then 30% of Speedup!) + * Improved memory protection tracking and signal handling, again + * Simplified mutex handling (faster, cleaner) + * Reduce memory used by the memory tracking (memory almost divide by 4 is some critical use case) + * Added d3dadaptor9 wrapping + * More wrapped libs (especially on the gtk familly) + * Improved/fixed some Syscall handling + * Refactored Strong Memory Model emulation (faster and more accurate) + * Added some more opcode to ARM64 Dynarec, and fixed some other + * Some fixes to flags handling in the Dynarec on some special cases + * Refactor library loading/unloading, with refcount. + * Some special cases fixes for dlopen (fixes deadcells, maybe others too) + * Improved mmap mapping, espcially with MAP_32BITS flag + * More wrapped functions and syscalls + * Lots of improvment in the Rounding of float & double (Dynarec and Interpreter), and proper handling of denormals when converting to/from 80 bits long double + * Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel) + * More support on the RV64 port + * More support to build under musl environment + + -- Sebastien Chevalier Thu, 10 Mar 2023 10:20:33 -0500 box64 (0.2.0) unstable; urgency=low - * Wrapped more vulkan function, dxvk 2.0 now works - * Added support for overridden malloc/free functions - * Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size) - * Improved elf loader - * Improved dlsym handling with RTLD_NEXT - * Added BOX64_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns. - * Added BOX64_BASH to setup x86_64 bash binary, so shell script can be run in x86_64 world - * Added BOX64_ROLLING_LOG to have details log only on crash - * Work on alignment for some of pthread structures - * More wrapped libraries in the gtk family - * Some fixes on the Dynarec x87 code (fixing a bunch of games like ut2004 or Piczle Puzzle) - * Improved TLS Size handling (Unity3D games now works) - * More PageSize Compile options - * Improved execv family of function to have better box64 integration - * Added support for wrapped libfuse so AppImage works - * Adjusted the binfmt integration so AppImage are automaticaly picked - * Improved FAudio, SDL2, GL (and more) wrapping - * More wrapped libs, like libEGL.so, to helps emulated Qt4/5 libs to load - * Improved Signal Handling and memory protection traking - * Some signature fixes to some wrapped functions (in libc) - * Added more syscalls - * Added a lot of new opcodes to the ARM64 Dynarec - * docs: add instructions for Debian-based Linux by @ryanfortner in #306 - * Fix typos and arch type string by @archanox in #321 - * Fix grammar by @Jai-JAP in #326 - * Enable 64k page size by @martinmanyhats in #334 - * Align address when call mprotect by @wannacu in #336 - * Add wrapped functions needed for 'ls -l'. by @stiltr in #294 - * add 18.04 tegra X1 github actions by @theofficialgman in #345 - * change order of matrix (to preview better under checkmark dropdown by @theofficialgman in #346 - * Backport SDL_DYNAPI_entry wrapper from box86. by @JohnnyonFlame in #374 - * Add SW64 base support by @wannacu in #382 - * fix overzealous replace in wrappers pathnames by @NobodyNada in #415 - * Create X64WINE.md by @WheezyE in #423 - * src: asm: Rename lr & fp registers to their x-equivalents by @fredldotme in #426 - * Malloc override by @ptitSeb in #437 - * Remove dynablocklist by @ptitSeb in #438 - * Fix Pkgbuilds by @Jai-JAP in #452 + * Wrapped more vulkan function, dxvk 2.0 now works + * Added support for overridden malloc/free functions + * Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size) + * Improved elf loader + * Improved dlsym handling with RTLD_NEXT + * Added BOX64_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns. + * Added BOX64_BASH to setup x86_64 bash binary, so shell script can be run in x86_64 world + * Added BOX64_ROLLING_LOG to have details log only on crash + * Work on alignment for some of pthread structures + * More wrapped libraries in the gtk family + * Some fixes on the Dynarec x87 code (fixing a bunch of games like ut2004 or Piczle Puzzle) + * Improved TLS Size handling (Unity3D games now works) + * More PageSize Compile options + * Improved execv family of function to have better box64 integration + * Added support for wrapped libfuse so AppImage works + * Adjusted the binfmt integration so AppImage are automaticaly picked + * Improved FAudio, SDL2, GL (and more) wrapping + * More wrapped libs, like libEGL.so, to helps emulated Qt4/5 libs to load + * Improved Signal Handling and memory protection traking + * Some signature fixes to some wrapped functions (in libc) + * Added more syscalls + * Added a lot of new opcodes to the ARM64 Dynarec + * docs: add instructions for Debian-based Linux by @ryanfortner in #306 + * Fix typos and arch type string by @archanox in #321 + * Fix grammar by @Jai-JAP in #326 + * Enable 64k page size by @martinmanyhats in #334 + * Align address when call mprotect by @wannacu in #336 + * Add wrapped functions needed for 'ls -l'. by @stiltr in #294 + * add 18.04 tegra X1 github actions by @theofficialgman in #345 + * change order of matrix (to preview better under checkmark dropdown by @theofficialgman in #346 + * Backport SDL_DYNAPI_entry wrapper from box86. by @JohnnyonFlame in #374 + * Add SW64 base support by @wannacu in #382 + * fix overzealous replace in wrappers pathnames by @NobodyNada in #415 + * Create X64WINE.md by @WheezyE in #423 + * src: asm: Rename lr & fp registers to their x-equivalents by @fredldotme in #426 + * Malloc override by @ptitSeb in #437 + * Remove dynablocklist by @ptitSeb in #438 + * Fix Pkgbuilds by @Jai-JAP in #452 -- Sebastien Chevalier Thu, 17 Nov 2022 11:20:33 -0500 diff --git a/docs/BUNDLE-X86-LIBS.md b/docs/BUNDLE-X86-LIBS.md index a6f91692d..cdacf8c46 100644 --- a/docs/BUNDLE-X86-LIBS.md +++ b/docs/BUNDLE-X86-LIBS.md @@ -78,13 +78,13 @@ Preference of operating system packages that provide a library: 2. DEBs from Debian 11 provide 5 years of updates. 3. EOPKG from Solus provide old variants of obscure 32-bit libraries. 4. XBPS from Void Linux provide updated variants of obscure 32-bit libraries. -5. Other (whereever a library is packaged) +5. Other (wherever a library is packaged) Some essential libraries will always be emulated and should be bundled. The full list can be found in the [in the core source code](https://github.com/ptitSeb/box64/blob/v0.4.0/src/core.c#L413). Some essential library files will never be emulated (only natively wrapped instead) and should not be bundled. This includes glibc, OpenGL, Vulkan, and X11/Xorg libraries. The full list can be found [in the library source code](https://github.com/ptitSeb/box64/blob/v0.4.0/src/librarian/library.c#L440). Other libraries with lots of dependencies, such as GTK, require all dependencies to be installed for emulation to work. This becomes dependency hell and should be avoided. -For finding package names that contian a specific library file, use the [pkgs.org website](https://pkgs.org/). Otherwise, use one of these package manager commands on a x86_64 Linux distribution: +For finding package names that contain a specific library file, use the [pkgs.org website](https://pkgs.org/). Otherwise, use one of these package manager commands on a x86_64 Linux distribution: - DEB - `apt-file ` - EOPKG diff --git a/docs/USAGE.md b/docs/USAGE.md index 2b0f2932f..2bbd6ab62 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -80,7 +80,7 @@ Optimize CALL/RET opcodes. Available in WowBox64. * 0: Do not optimize CALL/RET, use jump table. * 1: Try to optimize CALL/RET, skipping the jump table when possible. * 2: Try to optimize CALL/RET, skipping the jump table when possible, adding code to handle return to dirty/modified block. Does not work on WowBox64. [Default] - * 3: Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now. + * 3: Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use. ### BOX64_DYNAREC_DF diff --git a/docs/USAGE_CN.md b/docs/USAGE_CN.md index f7ec7edd6..f93c8f083 100644 --- a/docs/USAGE_CN.md +++ b/docs/USAGE_CN.md @@ -80,7 +80,7 @@ BOX64_DYNAREC_CALLRET=1 * 0: 不优化 CALL/RET,使用跳转表。 * 1: 尝试优化 CALL/RET,在可能的情况下跳过跳转表。 * 2: 尝试优化 CALL/RET,在可能的情况下跳过跳转表,同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。 [默认值] - * 3: 在 2 的基础上,对叶子函数进行分析,并将符合条件的叶子函数体复制到调用方。目前仅支持龙架构。 + * 3: 在 2 的基础上,额外跟踪代码块的使用情况,避免回收仍在使用中的代码块。 ### BOX64_DYNAREC_DF diff --git a/docs/box64.pod b/docs/box64.pod index 83621c376..40fc9f3e9 100644 --- a/docs/box64.pod +++ b/docs/box64.pod @@ -175,7 +175,7 @@ Optimize CALL/RET opcodes. Available in WowBox64. * 0 : Do not optimize CALL/RET, use jump table. * 1 : Try to optimize CALL/RET, skipping the jump table when possible. * 2 : Try to optimize CALL/RET, skipping the jump table when possible, adding code to handle return to dirty/modified block. Does not work on WowBox64. [Default] - * 3 : Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now. + * 3 : Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use. =item B =I<0|1> diff --git a/docs/gen/usage.json b/docs/gen/usage.json index e259d3ef7..1d0f49e17 100644 --- a/docs/gen/usage.json +++ b/docs/gen/usage.json @@ -309,7 +309,7 @@ }, { "key": "3", - "description": "Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now.", + "description": "Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use.", "default": false } ] diff --git a/docs/gen/usage_cn.json b/docs/gen/usage_cn.json index 7292afb68..7833debcf 100644 --- a/docs/gen/usage_cn.json +++ b/docs/gen/usage_cn.json @@ -107,7 +107,7 @@ "0": "不优化 CALL/RET,使用跳转表。", "1": "尝试优化 CALL/RET,在可能的情况下跳过跳转表。", "2": "尝试优化 CALL/RET,在可能的情况下跳过跳转表,同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。", - "3": "在 2 的基础上,对叶子函数进行分析,并将符合条件的叶子函数体复制到调用方。目前仅支持龙架构。" + "3": "在 2 的基础上,额外跟踪代码块的使用情况,避免回收仍在使用中的代码块。" } }, "BOX64_DYNAREC_DF": { diff --git a/external/musl/sincos.c b/external/musl/sincos.c index c8d866ba9..5183e43c1 100644 --- a/external/musl/sincos.c +++ b/external/musl/sincos.c @@ -10,7 +10,6 @@ * ==================================================== */ -#define _GNU_SOURCE #include "libm.h" void __cdecl sincos(double x, double *sin, double *cos) diff --git a/src/box64context.c b/src/box64context.c index 751b301ba..0756ca8f9 100644 --- a/src/box64context.c +++ b/src/box64context.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/custommem.c b/src/custommem.c index ec388e587..ea291f530 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/custommmap.c b/src/custommmap.c index d5ff368e1..ddd2646b1 100644 --- a/src/custommmap.c +++ b/src/custommmap.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 592a24727..790b42efd 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -230,25 +230,25 @@ int convert_bitmask(uint64_t bitmask); #define LDURSBx_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, 0b10, imm9, Rn, Rt)) #define LDURSBxw_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, (rex.w)?0b10:0b11, imm9, Rn, Rt)) -#define LDxw(A, B, C) if(unscaled) {LDURxw_I9(A, B, C);} else {LDRxw_U12(A, B, C);} -#define LDz(A, B, C) if(unscaled) {LDURz_I9(A, B, C);} else {LDRz_U12(A, B, C);} -#define LDx(A, B, C) if(unscaled) {LDURx_I9(A, B, C);} else {LDRx_U12(A, B, C);} -#define LDW(A, B, C) if(unscaled) {LDURw_I9(A, B, C);} else {LDRw_U12(A, B, C);} -#define LDH(A, B, C) if(unscaled) {LDURH_I9(A, B, C);} else {LDRH_U12(A, B, C);} -#define LDB(A, B, C) if(unscaled) {LDURB_I9(A, B, C);} else {LDRB_U12(A, B, C);} -#define LDSW(A, B, C) if(unscaled) {LDURSW_I9(A, B, C);} else {LDRSW_U12(A, B, C);} -#define LDSHxw(A, B, C) if(unscaled) {LDURSHxw_I9(A, B, C);} else {LDRSHxw_U12(A, B, C);} -#define LDSHx(A, B, C) if(unscaled) {LDURSHx_I9(A, B, C);} else {LDRSHx_U12(A, B, C);} -#define LDSHw(A, B, C) if(unscaled) {LDURSHw_I9(A, B, C);} else {LDRSHw_U12(A, B, C);} -#define LDSBxw(A, B, C) if(unscaled) {LDURSBxw_I9(A, B, C);} else {LDRSBxw_U12(A, B, C);} -#define LDSBx(A, B, C) if(unscaled) {LDURSBx_I9(A, B, C);} else {LDRSBx_U12(A, B, C);} -#define LDSBw(A, B, C) if(unscaled) {LDURSBw_I9(A, B, C);} else {LDRSBw_U12(A, B, C);} -#define STxw(A, B, C) if(unscaled) {STURxw_I9(A, B, C);} else {STRxw_U12(A, B, C);} -#define STz(A, B, C) if(unscaled) {STURz_I9(A, B, C);} else {STRz_U12(A, B, C);} -#define STx(A, B, C) if(unscaled) {STURx_I9(A, B, C);} else {STRx_U12(A, B, C);} -#define STW(A, B, C) if(unscaled) {STURw_I9(A, B, C);} else {STRw_U12(A, B, C);} -#define STH(A, B, C) if(unscaled) {STURH_I9(A, B, C);} else {STRH_U12(A, B, C);} -#define STB(A, B, C) if(unscaled) {STURB_I9(A, B, C);} else {STRB_U12(A, B, C);} +#define LDxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURxw(A, B, C);} else if(unscaled) {LDURxw_I9(A, B, C);} else {LDRxw_U12(A, B, C);}} while(0) +#define LDz(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURz(A, B, C);} else if(unscaled) {LDURz_I9(A, B, C);} else {LDRz_U12(A, B, C);}} while(0) +#define LDx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURx(A, B, C);} else if(unscaled) {LDURx_I9(A, B, C);} else {LDRx_U12(A, B, C);}} while(0) +#define LDW(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURw(A, B, C);} else if(unscaled) {LDURw_I9(A, B, C);} else {LDRw_U12(A, B, C);}} while(0) +#define LDH(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURH(A, B, C);} else if(unscaled) {LDURH_I9(A, B, C);} else {LDRH_U12(A, B, C);}} while(0) +#define LDB(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURB(A, B, C);} else if(unscaled) {LDURB_I9(A, B, C);} else {LDRB_U12(A, B, C);}} while(0) +#define LDSW(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSW(A, B, C);} else if(unscaled) {LDURSW_I9(A, B, C);} else {LDRSW_U12(A, B, C);}} while (0) +#define LDSHxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSHxw(A, B, C);} else if(unscaled) {LDURSHxw_I9(A, B, C);} else {LDRSHxw_U12(A, B, C);}} while (0) +#define LDSHx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSHx(A, B, C);} else if(unscaled) {LDURSHx_I9(A, B, C);} else {LDRSHx_U12(A, B, C);}} while (0) +#define LDSHw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSHw(A, B, C);} else if(unscaled) {LDURSHw_I9(A, B, C);} else {LDRSHw_U12(A, B, C);}} while (0) +#define LDSBxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSBxw(A, B, C);} else if(unscaled) {LDURSBxw_I9(A, B, C);} else {LDRSBxw_U12(A, B, C);}} while (0) +#define LDSBx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSBx(A, B, C);} else if(unscaled) {LDURSBx_I9(A, B, C);} else {LDRSBx_U12(A, B, C);}} while (0) +#define LDSBw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {LDAPURSBw(A, B, C);} else if(unscaled) {LDURSBw_I9(A, B, C);} else {LDRSBw_U12(A, B, C);}} while (0) +#define STxw(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURxw(A, B, C);} else if(unscaled) {STURxw_I9(A, B, C);} else {STRxw_U12(A, B, C);}} while(0) +#define STz(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURz(A, B, C);} else if(unscaled) {STURz_I9(A, B, C);} else {STRz_U12(A, B, C);}} while(0) +#define STx(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURx(A, B, C);} else if(unscaled) {STURx_I9(A, B, C);} else {STRx_U12(A, B, C);}} while(0) +#define STW(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURw(A, B, C);} else if(unscaled) {STURw_I9(A, B, C);} else {STRw_U12(A, B, C);}} while(0) +#define STH(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURH(A, B, C);} else if(unscaled) {STURH_I9(A, B, C);} else {STRH_U12(A, B, C);}} while(0) +#define STB(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {STLURB(A, B, C);} else if(unscaled) {STURB_I9(A, B, C);} else {STRB_U12(A, B, C);}} while(0) // STR #define STR_gen(size, op1, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b00<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt)) @@ -828,16 +828,16 @@ int convert_bitmask(uint64_t bitmask); #define VSTR64_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b11, 0b00, (imm9)&0b111111111, Rn, Vt)) #define VSTR128_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b00, 0b10, (imm9)&0b111111111, Rn, Vt)) -#define VLD128(A, B, C) if(unscaled) {VLDR128_I9(A, B, C);} else {VLDR128_U12(A, B, C);} -#define VLD64(A, B, C) if(unscaled) {VLDR64_I9(A, B, C);} else {VLDR64_U12(A, B, C);} -#define VLD32(A, B, C) if(unscaled) {VLDR32_I9(A, B, C);} else {VLDR32_U12(A, B, C);} -#define VLD16(A, B, C) if(unscaled) {VLDR16_I9(A, B, C);} else {VLDR16_U12(A, B, C);} -#define VLD8(A, B, C) if(unscaled) {VLDR8_I9(A, B, C);} else {VLDR8_U12(A, B, C);} -#define VST128(A, B, C) if(unscaled) {VSTR128_I9(A, B, C);} else {VSTR128_U12(A, B, C);} -#define VST64(A, B, C) if(unscaled) {VSTR64_I9(A, B, C);} else {VSTR64_U12(A, B, C);} -#define VST32(A, B, C) if(unscaled) {VSTR32_I9(A, B, C);} else {VSTR32_U12(A, B, C);} -#define VST16(A, B, C) if(unscaled) {VSTR16_I9(A, B, C);} else {VSTR16_U12(A, B, C);} -#define VST8(A, B, C) if(unscaled) {VSTR8_I9(A, B, C);} else {VSTR8_U12(A, B, C);} +#define VLD128(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR128(A, B, C);} else if(unscaled) {VLDR128_I9(A, B, C);} else {VLDR128_U12(A, B, C);}} while(0) +#define VLD64(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR64(A, B, C);} else if(unscaled) {VLDR64_I9(A, B, C);} else {VLDR64_U12(A, B, C);}} while(0) +#define VLD32(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR32(A, B, C);} else if(unscaled) {VLDR32_I9(A, B, C);} else {VLDR32_U12(A, B, C);}} while(0) +#define VLD16(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR16(A, B, C);} else if(unscaled) {VLDR16_I9(A, B, C);} else {VLDR16_U12(A, B, C);}} while(0) +#define VLD8(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VLDAPUR8(A, B, C);} else if(unscaled) {VLDR8_I9(A, B, C);} else {VLDR8_U12(A, B, C);}} while(0) +#define VST128(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR128(A, B, C);} else if(unscaled) {VSTR128_I9(A, B, C);} else {VSTR128_U12(A, B, C);}} while (0) +#define VST64(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR64(A, B, C);} else if(unscaled) {VSTR64_I9(A, B, C);} else {VSTR64_U12(A, B, C);}} while (0) +#define VST32(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR32(A, B, C);} else if(unscaled) {VSTR32_I9(A, B, C);} else {VSTR32_U12(A, B, C);}} while (0) +#define VST16(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR16(A, B, C);} else if(unscaled) {VSTR16_I9(A, B, C);} else {VSTR16_U12(A, B, C);}} while (0) +#define VST8(A, B, C) do {if(dyn->insts[ninst].use_lrcpc) {VSTLUR8(A, B, C);} else if(unscaled) {VSTR8_I9(A, B, C);} else {VSTR8_U12(A, B, C);}} while (0) #define VMEMW_gen(size, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt)) #define VLDR64_S9_postindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt)) @@ -2373,11 +2373,51 @@ int convert_bitmask(uint64_t bitmask); // LRCPC extension #define LDAPR_gen(sz, Rn, Rt) ((sz)<<30 | 0b111<<27 | 1<<23 | 1<<21 | 0b11111<<16 | 1<<15 | 0b100<<12 | (Rn)<<5 | (Rt)) -#define LDAPRx(Rt, Rn) EMIT(LDAPR_gen(0b11, Rn, Rt)) -#define LDAPRw(Rt, Rn) EMIT(LDAPR_gen(0b10, Rn, Rt)) -#define LDAPRxw(Rt, Rn) EMIT(LDAPR_gen(0b10+rex.w, Rn, Rt)) -#define LDAPRz(Rt, Rn) EMIT(LDAPR_gen(rex.is32bits?0b10:0b11, Rn, Rt)) -#define LDAPRH(Rt, Rn) EMIT(LDAPR_gen(0b01, Rn, Rt)) -#define LDAPRB(Rt, Rn) EMIT(LDAPR_gen(0b00, Rn, Rt)) +#define LDAPRx(Rt, Rn) LEMIT(LDAPR_gen(0b11, Rn, Rt)) +#define LDAPRw(Rt, Rn) LEMIT(LDAPR_gen(0b10, Rn, Rt)) +#define LDAPRxw(Rt, Rn) LEMIT(LDAPR_gen(0b10+rex.w, Rn, Rt)) +#define LDAPRz(Rt, Rn) LEMIT(LDAPR_gen(rex.is32bits?0b10:0b11, Rn, Rt)) +#define LDAPRH(Rt, Rn) LEMIT(LDAPR_gen(0b01, Rn, Rt)) +#define LDAPRB(Rt, Rn) LEMIT(LDAPR_gen(0b00, Rn, Rt)) + +// LRCPC2 extension + +#define LRCPC2_gen(sz, opc, imm9, Rn, Rt) ((sz)<<30 | 0b011001<<24 | (opc)<<22 | ((imm9)&0b111111111)<<12 | (Rn)<<5 | (Rt)) +#define STLURx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b11, 0b00, imm9, Rn, Rt)) +#define STLURw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10, 0b00, imm9, Rn, Rt)) +#define STLURxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10+rex.w, 0b00, imm9, Rn, Rt)) +#define STLURz(Rt, Rn, imm9) LEMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b00, imm9, Rn, Rt)) +#define STLURH(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b00, imm9, Rn, Rt)) +#define STLURB(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b00, imm9, Rn, Rt)) + +#define LDAPURx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b11, 0b01, imm9, Rn, Rt)) +#define LDAPURw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10, 0b01, imm9, Rn, Rt)) +#define LDAPURxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10+rex.w, 0b01, imm9, Rn, Rt)) +#define LDAPURz(Rt, Rn, imm9) LEMIT(LRCPC2_gen(rex.is32bits?0b10:0b11, 0b01, imm9, Rn, Rt)) +#define LDAPURH(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b01, imm9, Rn, Rt)) +#define LDAPURB(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b01, imm9, Rn, Rt)) +#define LDAPURSW(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b10, 0b10, imm9, Rn, Rt)) +#define LDAPURSHw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b11, imm9, Rn, Rt)) +#define LDAPURSHx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, 0b10, imm9, Rn, Rt)) +#define LDAPURSHxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b01, rex.w?0b10:0b11, imm9, Rn, Rt)) +#define LDAPURSBw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b11, imm9, Rn, Rt)) +#define LDAPURSBx(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, 0b10, imm9, Rn, Rt)) +#define LDAPURSBxw(Rt, Rn, imm9) LEMIT(LRCPC2_gen(0b00, rex.w?0b10:0b11, imm9, Rn, Rt)) + +#define NOLRCPC() dyn->insts[ninst].use_lrcpc=0 + +// LRCPC3 extension +#define LRCPC3_gen(sz, opc, imm9, Rn, Rt) ((sz)<<30 | 0b011101<<24 | (opc)<<22 | ((imm9)&0b111111111)<<12 | 0b10<<10 | (Rn)<<5 | (Rt)) +#define VLDAPUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b11, imm9, Vn, Vt));} while(0) +#define VLDAPUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b11, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b10, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b01, 0b01, imm9, Vn, Vt));} while(0) +#define VLDAPUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b01, imm9, Vn, Vt));} while(0) + +#define VSTLUR128(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b10, imm9, Vn, Vt));} while(0) +#define VSTLUR64(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b11, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR32(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b10, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR16(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b01, 0b00, imm9, Vn, Vt));} while(0) +#define VSTLUR8(Vt, Vn, imm9) do{if(!cpuext.lrcpc3) NOLRCPC(); else LEMIT(LRCPC3_gen(0b00, 0b00, imm9, Vn, Vt));} while(0) #endif //__ARM64_EMITTER_H__ diff --git a/src/dynarec/arm64/arm64_mapping.h b/src/dynarec/arm64/arm64_mapping.h index 407308a4a..a30a5764c 100644 --- a/src/dynarec/arm64/arm64_mapping.h +++ b/src/dynarec/arm64/arm64_mapping.h @@ -39,6 +39,32 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur */ // x86 Register mapping +#ifdef BOX64EC +// x18 is the TEB and x6 is guest R9, the other scratch registers are x1 to x5 +#define xRAX 10 +#define xRCX 11 +#define xRDX 12 +#define xRBX 8 +#define xRSP 20 +#define xRBP 21 +#define xRSI 16 +#define xRDI 17 +#define xR8 15 +#define xR9 6 +#define xR10 23 +#define xR11 9 +#define xR12 22 +#define xR13 25 +#define xR14 26 +#define xR15 19 +#define xFlags 7 +#define xRIP 27 + +// convert a x86 register to native according to the register mapping +#define TO_NAT(A) (((uint8_t[]){10, 11, 12, 8, 20, 21, 16, 17, 15, 6, 23, 9, 22, 25, 26, 19})[(A)]) +#define IS_GPR(A) (((uint8_t[]){0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, \ + 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0})[(A)]) +#else #define xRAX 10 #define xRCX 11 #define xRDX 12 @@ -62,6 +88,9 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur // convert a x86 register to native according to the register mapping #define TO_NAT(A) (xRAX + (A)) #define IS_GPR(A) ((A)>=xRAX && (A)<=xRIP) +#endif +// the Windows platform register, reloaded with the TEB after C calls +#define xTEB 18 // 32bits version #define wEAX xRAX @@ -87,8 +116,14 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur #define x3 3 #define x4 4 #define x5 5 +#ifdef BOX64EC +#define x6 BOX64EC_x6_IS_GUEST_R9_USE_xR9 +// x87pc is x5, a normal scratch: BOX64_DYNAREC_X87DOUBLE=2 precision tracking is not supported on Box64EC +#define x87pc 5 +#else #define x6 6 #define x87pc 7 +#endif // x87 can be a scratch, but check if it's used as x87 PC and restore if needed in that case // 32bits version of scratch #define w1 x1 @@ -96,7 +131,11 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur #define w3 x3 #define w4 x4 #define w5 x5 +#ifdef BOX64EC +#define w6 BOX64EC_w6_IS_GUEST_R9_USE_wR9 +#else #define w6 x6 +#endif #define w87pc x87pc // emu is r0 #define xEmu 0 diff --git a/src/dynarec/arm64/arm64_printer.c b/src/dynarec/arm64/arm64_printer.c index 22583cfa3..7565eaba7 100644 --- a/src/dynarec/arm64/arm64_printer.c +++ b/src/dynarec/arm64/arm64_printer.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #include #include @@ -209,12 +209,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) } if(isMask(opcode, "001110001x0iiiiiiiii00nnnnnttttt", &a)) { int offset = signExtend(imm, 9); - snprintf(buff, sizeof(buff), "LDURSB %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + snprintf(buff, sizeof(buff), "LDURSB %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } if(isMask(opcode, "011110001x0iiiiiiiii00nnnnnttttt", &a)) { int offset = signExtend(imm, 9); - snprintf(buff, sizeof(buff), "LDURSH %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + snprintf(buff, sizeof(buff), "LDURSH %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } if(isMask(opcode, "10111000100iiiiiiiii00nnnnnttttt", &a)) { @@ -222,6 +222,37 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "LDURSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } + if(isMask(opcode, "1x011001010iiiiiiiii00nnnnnttttt", &a)) { + int size = (opcode>>30)&3; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPUR %s, [%s, %s0x%x]", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "00011001010iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURB %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "01011001010iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "000110011x0iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURSB %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "010110011x0iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURSH %s, [%s, %s0x%x]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "10011001100iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "LDAPURSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } if(isMask(opcode, "1x111000000iiiiiiiii00nnnnnttttt", &a)) { int size = (opcode>>30)&3; int offset = signExtend(imm, 9); @@ -238,6 +269,22 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "STURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); return buff; } + if(isMask(opcode, "1x011001000iiiiiiiii00nnnnnttttt", &a)) { + int size = (opcode>>30)&3; + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STLUR %s, [%s, %s0x%x]", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "00011001000iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STLURB %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } + if(isMask(opcode, "01011001000iiiiiiiii00nnnnnttttt", &a)) { + int offset = signExtend(imm, 9); + snprintf(buff, sizeof(buff), "STLURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset)); + return buff; + } if(isMask(opcode, "1x11100101iiiiiiiiiiiinnnnnttttt", &a)) { int size = (opcode>>30)&3; int offset = (imm)<f; CALL_S(const_native_br, -1); LOAD_XEMU_CALL(xRIP); + dyn->f = f_save; } else { INST_NAME("Illegal 62"); if(BOX64DRENV(dynarec_safeflags)>1) { @@ -1011,10 +1014,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETEW(x1, 0); GETGW(x2); // Extract RPL (low 2 bits) - UBFXw(x6, ed, 0, 2); + UBFXw(x5, ed, 0, 2); UBFXw(x4, gd, 0, 2); // need_update = (dst_rpl < src_rpl) - CMPSw_REG(x6, x4); + CMPSw_REG(x5, x4); CSETw(x5, cLT); // ZF = need_update BFIw(xFlags, x5, F_ZF, 1); @@ -1469,7 +1472,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop=F8; GETEB(x1, 0); GETGB(x2); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8(dyn, ninst, x1, x2, x3, x4); break; case 0x85: INST_NAME("TEST Ed, Gd"); @@ -1477,7 +1480,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop=F8; GETGD; GETED(0); - emit_test32(dyn, ninst, rex, ed, gd, x3, x5, x6); + emit_test32(dyn, ninst, rex, ed, gd, x3, x5); break; case 0x86: INST_NAME("(LOCK)XCHG Eb, Gb"); @@ -1604,6 +1607,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { // mem <= reg IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, &lock, 0, 0); if(gd==wback) { MOVx_REG(x2, wback); @@ -1616,9 +1620,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin // gd restored after that } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, &lock, 0, 0); - if(!lock && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { - DMB_ISH(); - lock = 1; + if(!lock && !dyn->insts[ninst].use_lrcpc && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { + if(!dyn->insts[ninst].x64.strongmem && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) + dyn->insts[ninst].use_lrcpc = 1; + else { + DMB_ISH(); + lock = 1; + } } STxw(gd, ed, fixedaddress); } @@ -1667,8 +1675,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3))); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0); - if(!lock && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { - lock = 1; + if(!lock && !dyn->insts[ninst].use_lrcpc && BOX64ENV(unity) && !VolatileRangesContains(ip) && ((fixedaddress==0x80) || (fixedaddress==0x84) || (fixedaddress==0xc0) || (fixedaddress==0xc4))) { + if(!dyn->insts[ninst].x64.strongmem && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) + dyn->insts[ninst].use_lrcpc = 1; + else + lock = 1; } SMREADLOCK(lock); LDxw(gd, ed, fixedaddress); @@ -2024,6 +2035,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP MOVSB"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2085,8 +2097,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRSI, xRSI); } GETDIR(x3, 1); - LDRB_U12(x1, xRSI, 0); - STRB_U12(x1, xRDI, 0); + unscaled = 0; + LDB(x1, xRSI, 0); + STB(x1, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); } @@ -2097,6 +2110,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP MOVSD"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2121,8 +2135,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRSI, xRSI); } GETDIR(x3, rex.w?8:4); - LDRxw_U12(x1, xRSI, 0); - STRxw_U12(x1, xRDI, 0); + unscaled = 0; + LDxw(x1, xRSI, 0); + STxw(x1, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); } @@ -2140,6 +2155,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2162,6 +2178,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("CMPSB"); @@ -2172,8 +2189,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } GETDIR(x3, 1); SMREAD(); - LDRB_U12(x1, xRSI, 0); - LDRB_U12(x2, xRDI, 0); + unscaled = 0; + LDB(x1, xRSI, 0); + LDB(x2, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5); @@ -2192,6 +2210,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -2214,6 +2233,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("CMPSD"); @@ -2224,8 +2244,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } GETDIR(x3, rex.w?8:4); SMREAD(); - LDRxw_U12(x1, xRSI, 0); - LDRxw_U12(x2, xRDI, 0); + unscaled = 0; + LDxw(x1, xRSI, 0); + LDxw(x2, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5); @@ -2237,19 +2258,19 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); UXTBx(x1, xRAX); u8 = F8; - MOV32w(x2, u8); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8c(dyn, ninst, x1, u8, x3, x4); break; case 0xA9: INST_NAME("TEST EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING); i64 = F32S; - emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5); + emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; case 0xAA: if(rex.rep) { INST_NAME("REP STOSB"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } @@ -2301,7 +2322,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRDI, xRDI); } GETDIR(x3, 1); - STRB_U12(xRAX, xRDI, 0); + unscaled = 0; + STB(xRAX, xRDI, 0); ADDy_REG(xRDI, xRDI, x3); } SMWRITE(); @@ -2310,6 +2332,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP STOSD"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } @@ -2331,7 +2354,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRDI, xRDI); } GETDIR(x3, rex.w?8:4); - STRxw_U12(xRAX, xRDI, 0); + unscaled = 0; + STxw(xRAX, xRDI, 0); ADDy_REG(xRDI, xRDI, x3); } SMWRITE(); @@ -2342,6 +2366,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { INST_NAME("LODSB"); } + NOLRCPC(); GETDIR(x1, 1); SMREAD(); if(rex.rep) { @@ -2365,6 +2390,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { INST_NAME("LODSD"); } + NOLRCPC(); GETDIR(x1, rex.w?8:4); if(rex.rep) { CBZx_NEXT(xRCX); @@ -2381,6 +2407,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 0xAE: + NOLRCPC(); switch(rex.rep) { case 1: case 2: @@ -2412,6 +2439,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("SCASB"); @@ -2428,6 +2456,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 0xAF: + NOLRCPC(); switch(rex.rep) { case 1: case 2: @@ -2458,6 +2487,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("SCASD"); @@ -2892,6 +2922,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { // mem <= i32 IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, &lock, 0, 4); i64 = F32S; if(i64) { @@ -2955,6 +2986,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); if(rex.w) {POP2(xRIP, x3);} else {POP2_32(xRIP, x3);} + TBZ_MARK(x3, 0); + TBZ_MARK(x3, 1); //GP if CS is incorect STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); if(u16<0x1000) ADDz_U12(xRSP, xRSP, u16); @@ -2963,6 +2996,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ADDz_REG(xRSP, xRSP, x1); } ret_to_next(dyn, ip, ninst, rex); + MARK; + ADDx_U12(xRSP, xRSP, (rex.w?8:4)*2); + MOV64x(xRIP, ip); // move back RIP to the opcode + CALL_S(const_native_priv, -1); + jump_to_epilog(dyn, 0, xRIP, ninst); *need_epilog = 0; *ok = 0; break; @@ -2971,8 +3009,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); if(rex.w) {POP2(xRIP, x3);} else {POP2_32(xRIP, x3);} + TBZ_MARK(x3, 0); + TBZ_MARK(x3, 1); //GP if CS is incorect STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); ret_to_next(dyn, ip, ninst, rex); + MARK; + ADDx_U12(xRSP, xRSP, (rex.w?8:4)*2); + MOV64x(xRIP, ip); // move back RIP to the opcode + CALL_S(const_native_priv, -1); + jump_to_epilog(dyn, 0, xRIP, ninst); *need_epilog = 0; *ok = 0; break; @@ -3538,7 +3583,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETED(0); if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} CBZw_NEXT(x3); - emit_rcl32(dyn, ninst, rex, ed, x3, x5, x4, x6); + emit_rcl32(dyn, ninst, rex, ed, x3, x5, x4); WBACK; break; case 3: @@ -3557,7 +3602,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETED(0); if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} CBZw_NEXT(x3); - emit_rcr32(dyn, ninst, rex, ed, x3, x5, x4, x6); + emit_rcr32(dyn, ninst, rex, ed, x3, x5, x4); WBACK; break; case 4: @@ -3939,6 +3984,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOV64x(x4, j64); } LDRx_U12(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x1, x2, x3); BR(x4); } CLEARIP(); @@ -4077,8 +4124,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEB(x1, 1); u8 = F8; - MOV32w(x2, u8); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8c(dyn, ninst, x1, u8, x3, x4); break; case 2: INST_NAME("NOT Eb"); @@ -4243,7 +4289,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEDH(x1, 4); i64 = F32S; - emit_test32c(dyn, ninst, rex, ed, i64, x3, x4, x5); + emit_test32c(dyn, ninst, rex, ed, i64, x3, x4); break; case 2: INST_NAME("NOT Ed"); @@ -4637,6 +4683,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LDRx_U12(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x1, x2, x3); BR(x4); } CLEARIP(); @@ -4653,6 +4701,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin LDxw(x1, wback, 0); ed = x1; LDH(x3, wback, rex.w?8:4); + TBZ(x3, 0, 4+4); + TBNZ_MARK2(x3, 1); + // Bad CS => GP + CALL_S(const_native_priv, -1); + jump_to_epilog(dyn, 0, xRIP, ninst); + MARK2; LDH(x5, xEmu, offsetof(x64emu_t, segs[_CS])); if (BOX64DRENV(dynarec_callret) && BOX64DRENV(dynarec_bigblock) > 1) { BARRIER(BARRIER_FULL); @@ -4682,7 +4736,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STPx_S7_preindex(x4, xRIP, xSP, -16); } if (rex.w) PUSH2(x5, xRIP); else PUSH2_32(x5, xRIP); - STH(x3, xEmu, offsetof(x64emu_t, segs[_CS])); + STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); jump_to_next(dyn, 0, ed, ninst, rex.is32bits); CALLRET_RET(can_continue); if (BOX64DRENV(dynarec_callret) && !can_continue) { @@ -4692,6 +4746,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LDRx_U12(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x1, x2, x3); BR(x4); } CLEARIP(); @@ -4718,7 +4774,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin LDxw(x1, wback, 0); ed = x1; LDH(x3, wback, rex.w?8:4); - STH(x3, xEmu, offsetof(x64emu_t, segs[_CS])); + STRH_U12(x3, xEmu, offsetof(x64emu_t, segs[_CS])); jump_to_next(dyn, 0, ed, ninst, rex.w?0:1); *need_epilog = 0; *ok = 0; diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c index aed2b81fd..4468898ac 100644 --- a/src/dynarec/arm64/dynarec_arm64_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_0f.c @@ -298,6 +298,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); if(wback!=x1) { MOVx_REG(x1, wback); @@ -502,6 +503,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin UDF(0); } else { INST_NAME("MOVNTPS Ex,Gx"); + NOLRCPC(); GETG; v0 = sse_get_reg(dyn, ninst, x1, gd, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0); @@ -2594,6 +2596,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xC3: INST_NAME("MOVNTI Ed, Gd"); + NOLRCPC(); nextop=F8; GETGD; if(MODREG) { // reg <= reg @@ -2989,6 +2992,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xE7: INST_NAME("MOVNTQ Em, Gm"); + NOLRCPC(); nextop = F8; gd = (nextop&0x38)>>3; if(MODREG) { diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index 276a43706..a4f8aa40c 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #include #include @@ -605,7 +605,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop = F8; GETEW(x1, 0); GETGW(x2); - emit_test16(dyn, ninst, x1, x2, x3, x4, x5); + emit_test16(dyn, ninst, x1, x2, x3, x4); break; case 0x87: @@ -884,6 +884,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(rex.rep) { INST_NAME("REP MOVSW"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -908,8 +909,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRSI, xRSI); } GETDIR(x3, 2); - LDRH_U12(x1, xRSI, 0); - STRH_U12(x1, xRDI, 0); + unscaled = 0; + LDH(x1, xRSI, 0); + STH(x1, xRDI, 0); ADDy_REG(xRSI, xRSI, x3); ADDy_REG(xRDI, xRDI, x3); } @@ -928,6 +930,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); MOVw_REG(xRSI, xRSI); @@ -950,6 +953,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("CMPSW"); @@ -973,13 +977,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); u16 = F16; UBFXx(x1, xRAX, 0, 16); - emit_test16c(dyn, ninst, x1, u16, x3, x4, x5); + emit_test16c(dyn, ninst, x1, u16, x3, x4); break; case 0xAB: if(rex.rep) { INST_NAME("REP STOSW"); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } @@ -1001,7 +1006,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRDI, xRDI); } GETDIR(x3, 2); - STRH_U12(xRAX, xRDI, 0); + unscaled = 0; + STH(xRAX, xRDI, 0); ADDy_REG(xRDI, xRDI, x3); } SMWRITE(); @@ -1050,6 +1056,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); + NOLRCPC(); if(rex.is67 && !rex.is32bits) { MOVw_REG(xRDI, xRDI); } @@ -1070,6 +1077,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZx_MARK2(xRCX); MARK3; // end emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5); + STOP_NATIVE_FLAGS(dyn, ninst); break; default: INST_NAME("SCASW"); @@ -1557,7 +1565,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETEW(x1, 2); u16 = F16; - emit_test16c(dyn, ninst, x1, u16, x3, x4, x5); + emit_test16c(dyn, ninst, x1, u16, x3, x4); break; case 2: INST_NAME("NOT Ew"); diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index ba7ce5350..2eeaacbe4 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -951,9 +951,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } } } else { - MRS_nzcv(x3); - BFIx(x3, xFlags, 29, 1); // set C - MSR_nzcv(x3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(x3); + BFIx(x3, xFlags, 29, 1); // set C + MSR_nzcv(x3); // load CC into ARM CF + } } IFX(X_CF) { ADCSxw_REG(gd, gd, ed); @@ -1320,6 +1324,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); @@ -1330,8 +1336,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n MOVx_REG(x2, xRDX); MOVx_REG(x4, xRAX); u8 = F8; - MOV32w(x5, u8); - MOV32w(x6, rex.w); + MOV32w(x5, u8 | (rex.w << 8)); // REX.W in bit 8 of the imm8 argument CALL(const_sse42_compare_string_explicit_len, x1); q0 = sse_get_reg_empty(dyn, ninst, x2, 0); if(u8&0b1000000) { @@ -1409,6 +1414,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n VMOVBto(x2, d0, 0); BFIw(x1, x2, 8, 8); // insert } +#ifdef BOX64EC + int lreg = x2; // no x6 (guest R9): lreg is lost in min(lmem, lreg) and recomputed for SF +#else + int lreg = x6; +#endif // get abs of eax / edx and find min ADDSxw_U12(x2, xRAX, 0); Bcond(cPL, 4+4); @@ -1417,17 +1427,24 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n Bcond(cPL, 4+4); NEGxw_REG(x3, x3); MOV32w(x4, (u8&1)?8:16); - CMPSw_REG(x3, x4); - CSELw(x3, x3, x4, cLO); // x3 is lmem - CMPSw_REG(x2, x4); - CSELw(x6, x2, x4, cLO); // x6 is lreg - CMPSw_REG(x6, x3); - CSELw(x5, x3, x6, cLT); // x5 is max(lmem, lreg) - CSELw(x2, x6, x3, cLT); // x2 is min(lmem, lreg) + if(rex.w) { + CMPSx_REG(x3, x4); + CSELx(x3, x3, x4, cLO); // x3 is lmem + CMPSx_REG(x2, x4); + CSELx(lreg, x2, x4, cLO); + } else { + CMPSw_REG(x3, x4); + CSELw(x3, x3, x4, cLO); // x3 is lmem + CMPSw_REG(x2, x4); + CSELw(lreg, x2, x4, cLO); + } + CMPSw_REG(lreg, x3); + CSELw(x5, x3, lreg, cLT); // x5 is max(lmem, lreg) + CSELw(x2, lreg, x3, cLT); // x2 is min(lmem, lreg) // x2 is min length 0-n_packed MVNw_REG(x4, xZR); - LSLw_REG(x87pc, x4, x2); - BICw_REG(x1, x1, x87pc); + LSLw_REG(x2, x4, x2); + BICw_REG(x1, x1, x2); LSLw_REG(x4, x4, x5); ORRw_REG(x1, x1, x4); ANDw_mask(x1, x1, 0, (u8&1)?7:15); @@ -1459,8 +1476,17 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n BFIw(xFlags, x5, F_ZF, 1); } IFX(X_SF) { +#ifdef BOX64EC + // lreg was overwritten by min(lmem, lreg), recompute it from abs(RAX) + ADDSxw_U12(x2, xRAX, 0); + Bcond(cPL, 4+4); + NEGxw_REG(x2, x2); + CMPSxw_REG(x2, x4); + CSETw(x5, cLO); +#else CMPSw_REG(x6, x4); CSETw(x5, cLT); +#endif BFIw(xFlags, x5, F_SF, 1); } } @@ -1485,11 +1511,15 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n SETFLAGS(X_ALL, SF_SET_DF); if(gd>7) // no need to reflect cache as xmm0-xmm7 will be saved before the function call anyway sse_reflect_reg(dyn, ninst, gd); + else + sse_mark_used(dyn, ninst, gd); ADDx_U12(x3, xEmu, offsetof(x64emu_t, xmm[gd])); if(MODREG) { ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); @@ -1500,8 +1530,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n MOVx_REG(x2, xRDX); MOVx_REG(x4, xRAX); u8 = F8; - MOV32w(x5, u8); - MOV32w(x6, rex.w); + MOV32w(x5, u8 | (rex.w << 8)); // REX.W in bit 8 of the imm8 argument CALL(const_sse42_compare_string_explicit_len, x1); } if(u8&0b1000000) { @@ -1529,6 +1558,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); @@ -1578,11 +1609,15 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETG; if(gd>7) sse_reflect_reg(dyn, ninst, gd); + else + sse_mark_used(dyn, ninst, gd); ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[gd])); if(MODREG) { ed = (nextop&7)+(rex.b<<3); if(ed>7) sse_reflect_reg(dyn, ninst, ed); + else + sse_mark_used(dyn, ninst, ed); ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed])); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1); @@ -2455,7 +2490,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = TO_NAT((nextop & 7) + (rex.b << 3)); } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x1, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2; LDH(x1, x3, fixedaddress); @@ -2499,7 +2534,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n UFLAG_IF { CBZw_NEXT(x4); } +#ifdef BOX64EC + // x1 to x5 are all in use and x6 is guest R9, so the address in x3 goes through the emu + if(wback==x3) STRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); + emit_shld16(dyn, ninst, ed, gd, x4, x5, x3); + if(wback==x3) LDRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); +#else emit_shld16(dyn, ninst, ed, gd, x4, x5, x6); +#endif EWBACK; break; @@ -2516,7 +2558,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; } else { - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x4, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2; LDH(x4, x3, fixedaddress); @@ -2569,7 +2611,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n CBZw_NEXT(x4); } else { } +#ifdef BOX64EC + // as SHLD, the address in x3 goes through the emu + if(wback==x3) STRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); + emit_shrd16(dyn, ninst, ed, gd, x4, x5, x3); + if(wback==x3) LDRx_U12(x3, xEmu, offsetof(x64emu_t, scratch[0])); +#else emit_shrd16(dyn, ninst, ed, gd, x4, x5, x6); +#endif EWBACK; break; case 0xAE: @@ -2642,7 +2691,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n wback = 0; } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x4, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2; LDH(x4, x3, fixedaddress); @@ -2787,7 +2836,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n wback = 0; } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0); SBFXx(x4, gd, 4, 12); // r1 = (gw>>4) ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2; LDH(x4, x3, fixedaddress); @@ -2928,10 +2977,12 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETGW(x1); GETEW(x2, 0); u8 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); - if (!(MODREG && wback == u8)) MOVx_REG(x6, ed); emit_add16(dyn, ninst, ed, gd, x4, x5); EWBACK; - if (!(MODREG && wback == u8)) BFIx(u8, x6, 0, 16); + if (!(MODREG && wback == u8)) { + SUBw_REG(gd, ed, gd); // the old Ew is the sum minus Gw + BFIx(u8, gd, 0, 16); + } break; case 0xC2: INST_NAME("CMPPD Gx, Ex, Ib"); diff --git a/src/dynarec/arm64/dynarec_arm64_66f0.c b/src/dynarec/arm64/dynarec_arm64_66f0.c index 5568a05b2..7a02c4517 100644 --- a/src/dynarec/arm64/dynarec_arm64_66f0.c +++ b/src/dynarec/arm64/dynarec_arm64_66f0.c @@ -115,7 +115,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n INST_NAME("LOCK CMPXCHG Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; - UXTHw(x6, xRAX); + UXTHw(x5, xRAX); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); if(!ALIGNED_ATOMICH) { if(cpuext.uscat) { @@ -129,12 +129,12 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } // Aligned version if(cpuext.atomics) { - MOVw_REG(x1, x6); + MOVw_REG(x1, x5); CASALH(x1, gd, wback); } else { MARKLOCK; LDAXRH(x1, wback); - CMPSw_REG(x6, x1); + CMPSw_REG(x5, x1); B_MARK(cNE); // EAX == Ed STLXRH(x4, gd, wback); @@ -149,7 +149,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n LDAXRB(x3, wback); // dummy read, to arm the write... SUBw_UXTB(x3, x3, x1); CBNZw_MARK3(x3); - CMPSw_REG(x6, x1); + CMPSw_REG(x5, x1); B_MARK(cNE); // EAX == Ed STLXRB(x4, gd, wback); @@ -158,7 +158,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } MARK; // Common part (and fallback for EAX != Ed) - UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);} + UFLAG_IF {emit_cmp16(dyn, ninst, x5, x1, x3, x4, x2);} BFIx(xRAX, x1, 0, 16); } break; @@ -211,11 +211,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n SETFLAGS(X_ALL, SF_SET_PENDING); GETGW(x5); addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRH(x1, wback); emit_adc16(dyn, ninst, x1, x5, x3, x4); STLXRH(x3, x1, wback); @@ -362,11 +358,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1); if(opcode==0x81) i16 = F16S; else i16 = F8S; MOV32w(x5, (uint16_t)i16); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRH(x1, wback); emit_adc16(dyn, ninst, x1, x5, x3, x4); STLXRH(x3, x1, wback); @@ -387,11 +379,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1); if(opcode==0x81) i16 = F16S; else i16 = F8S; MOV32w(x5, (uint16_t)i16); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRH(x1, wback); emit_sbb16(dyn, ninst, x1, x5, x3, x4); STLXRH(x3, x1, wback); diff --git a/src/dynarec/arm64/dynarec_arm64_arch.c b/src/dynarec/arm64/dynarec_arm64_arch.c index 1622d02d4..ff4fdc22d 100644 --- a/src/dynarec/arm64/dynarec_arm64_arch.c +++ b/src/dynarec/arm64/dynarec_arm64_arch.c @@ -13,6 +13,11 @@ #include "dynarec_arm64_arch.h" #include "dynarec_arm64_functions.h" #include "dynarec_native.h" +#include "custommem.h" +#include "khash.h" + +KHASH_SET_INIT_INT64(lrcpc) +static kh_lrcpc_t *lrcpc = NULL; //order might be important, so define SUPER for the right one #define SUPER() \ @@ -68,6 +73,7 @@ typedef struct arch_arch_s SUPER() #undef GO uint16_t unaligned:1; + uint16_t lrcpc:1; uint16_t seq:10; // how many instruction on the same values } arch_arch_t; @@ -77,6 +83,7 @@ typedef struct arch_build_s SUPER() #undef GO uint8_t unaligned; + uint8_t lrcpc; #define GO(A) arch_##A##_t A##_; SUPER() #undef GO @@ -92,16 +99,18 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa arch->flags = 1; arch->flags_.defered = (dyn->insts[ninst].f_entry!=status_none && dyn->insts[ninst].f_entry!=status_none_pending); uint8_t flags = dyn->insts[ninst].need_nat_flags | dyn->insts[ninst].before_nat_flags; - arch->flags_.vf = flags&NF_VF; - arch->flags_.nf = flags&NF_SF; - arch->flags_.eq = flags&NF_EQ; - arch->flags_.cf = flags&NF_CF; + arch->flags_.vf = !!(flags&NF_VF); + arch->flags_.nf = !!(flags&NF_SF); + arch->flags_.eq = !!(flags&NF_EQ); + arch->flags_.cf = !!(flags&NF_CF); if(arch->flags_.cf) arch->flags_.inv_cf = !dyn->insts[ninst].normal_carry; - arch->flags_.pf_v = flags&NF_PF_V; + arch->flags_.pf_v = !!(flags&NF_PF_V); } // opcode can handle unaligned arch->unaligned = dyn->insts[ninst].unaligned; + // opcode has lrcpc opcode in it + arch->lrcpc = dyn->insts[ninst].has_lrcpc; if(!noarch) { // got through all naoncache to gather regs assignments if(dyn->use_x87 || dyn->use_mmx || dyn->use_xmm || dyn->use_ymm) { @@ -121,11 +130,11 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa arch->ymm = 1; arch->ymm_.ymm |= 1<insts[ninst].n.neoncache[i].n; idx = i; - if(idx>=EMM0 && idx<=EMM0+8) + if(idx>=EMM0 && idxymm_.ymm_pos |= idx<<(dyn->insts[ninst].n.neoncache[i].n*4); + arch->ymm_.ymm_pos |= (uint64_t)idx<<(dyn->insts[ninst].n.neoncache[i].n*4); break; case NEON_CACHE_ST_D: arch->x87 = 1; @@ -163,7 +172,7 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa arch->x87_.delta = dyn->insts[ninst].n.x87stack; } } - return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned; + return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned + arch->lrcpc; } static int sizeof_arch(arch_arch_t* arch) @@ -218,6 +227,7 @@ static void build_next(arch_arch_t* arch, arch_build_t* build) SUPER() #undef GO arch->unaligned = build->unaligned; + arch->lrcpc = build->lrcpc; arch->seq = 0; void* p = ((void*)arch)+sizeof(arch_arch_t); #define GO(A) \ @@ -310,6 +320,8 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) if(flags->defered) { CHECK_FLAGS(emu); //return; + } else { + emu->df = d_none; } if(flags->nf) { CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<x87, x87->x87_pos, x87->x87_type, fpsimd); - emu->top -= x87->delta; + if (x87->delta) emu->top = (emu->top - x87->delta) & 7; for(int i=0; i<8; ++i) { if(x87->x87&(1<x87_pos>>(i*4))&0x0f); @@ -421,3 +433,53 @@ int arch_unaligned(dynablock_t* db, uintptr_t x64pc) } return arch->unaligned; } + +int arch_lrcpc(dynablock_t* db, uintptr_t x64pc) +{ + if(!db) + return 0; + if(!db->arch_size || !db->arch) + return 0; + int ninst = getX64AddressInst(db, x64pc); + if(ninst<0) { + return 0; + } + // look for state at ninst + arch_arch_t* arch = db->arch; + arch_arch_t* next = arch; + int i = -1; + while(iseq; + next = (arch_arch_t*)((uintptr_t)next + sizeof_arch(arch)); + } + return arch->lrcpc; +} + +void add_lrcpc_address(uintptr_t addr) +{ + if(!lrcpc) + lrcpc = kh_init(lrcpc); + khint_t k; + int ret; + k = kh_put(lrcpc, lrcpc, addr, &ret); // just add +} + +int is_addr_lrcpc(uintptr_t addr) +{ + if(!lrcpc) + return 0; + khint_t k = kh_get(lrcpc, lrcpc, addr); + return (k==kh_end(lrcpc))?0:1; +} + +int mark_db_lrcpc(dynablock_t* db, uintptr_t x64pc) +{ + add_lrcpc_address(x64pc); + if(db->to_delete) + return 2; // already marked + db->to_delete = 1; // mark block for deletion + MarkDynablock(db); // and mark it as dirty +if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address %p as avoid lrcpc\n", db, (void*)x64pc); + return 2; // marked, exit handling... +} diff --git a/src/dynarec/arm64/dynarec_arm64_arch.h b/src/dynarec/arm64/dynarec_arm64_arch.h index c4a63b212..ef8f366aa 100644 --- a/src/dynarec/arm64/dynarec_arm64_arch.h +++ b/src/dynarec/arm64/dynarec_arm64_arch.h @@ -22,4 +22,9 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) #endif // get if instruction can be regenerated for unaligned access int arch_unaligned(dynablock_t* db, uintptr_t x64pc); +// get if instruction has lrcpc so it can be regenerated without +int arch_lrcpc(dynablock_t* db, uintptr_t x64pc); +void add_lrcpc_address(uintptr_t addr); +int is_addr_lrcpc(uintptr_t addr); +int mark_db_lrcpc(dynablock_t* db, uintptr_t x64pc); #endif // __DYNAREC_ARM_ARCH_H__ diff --git a/src/dynarec/arm64/dynarec_arm64_avx_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_0f.c index 97db6dacb..5cce52f5f 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_0f.c @@ -269,6 +269,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int UDF(0); } else { INST_NAME("VMOVNTPS Ex, Gx"); + NOLRCPC(); GETG; v0 = sse_get_reg(dyn, ninst, x1, gd, 0); if(vex.l) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c index c67c4b4c2..97fe0b184 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c @@ -254,15 +254,15 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i GETGD; GETED(0); GETVD; - UXTBw(x6, vd); - CMPSw_U12(x6, rex.w ? 64 : 32); + UXTBw(x5, vd); + CMPSw_U12(x5, rex.w ? 64 : 32); CSETMxw(x2, cPL); IFX(X_CF) { BFIw(xFlags, x2, F_CF, 1); } MVNxw_REG(x2, x2); //prepare mask B_MARK(cPL); - LSLxw_REG(x2, x2, x6); + LSLxw_REG(x2, x2, x5); MARK; need_tst = 0; IFX(X_ZF) need_tst = 1; diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c index b68f8e833..7765aea54 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c @@ -244,6 +244,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2B: INST_NAME("VMOVNTPD Ex,Gx"); + NOLRCPC(); nextop = F8; GETG; if(MODREG) { @@ -442,7 +443,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, case 0x5B: INST_NAME("VCVTPS2DQ Gx, Ex"); nextop = F8; - u8 = sse_setround(dyn, ninst, x1, x2, x6); + u8 = sse_setround(dyn, ninst, x3, x2, x4); // the address below can use x2 and x3, x4 keeps the old FPCR if(!BOX64ENV(dynarec_fastround) && !cpuext.frintts) { d0 = fpu_get_scratch(dyn, ninst); d1 = fpu_get_scratch(dyn, ninst); @@ -1784,6 +1785,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, break; case 0xE7: INST_NAME("VMOVNTDQ Ex,Gx"); + NOLRCPC(); nextop = F8; GETG; if(MODREG) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c index c5b3d9484..5b80be2cd 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c @@ -643,6 +643,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip break; case 0x2A: INST_NAME("VMOVNTDQA Gx, Ex"); + NOLRCPC(); nextop = F8; GETG; if(MODREG) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c b/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c index e445260fd..188444db9 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c @@ -510,17 +510,17 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip } u8 = F8; if(u8&4) { - s0 = sse_setround(dyn, ninst, x1, x2, x6); + s0 = sse_setround(dyn, ninst, x1, x2, x5); } else { u8&=3; if(u8==1) u8=2; else if(u8==2) u8=1; MRS_fpcr(x1); // get fpscr MOV32w(x2, u8); - MOVx_REG(x6, x1); + MOVx_REG(x5, x1); BFIx(x1, x2, 22, 2); // inject new round MSR_fpcr(x1); // put new fpscr - s0 = x6; + s0 = x5; } FCVTN16(v1, v0); if(vex.l) { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c index fc7e7fd37..8757f7836 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c @@ -586,11 +586,12 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, case 0xE6: INST_NAME("VCVTPD2DQ Gx, Ex"); nextop = F8; - u8 = sse_setround(dyn, ninst, x1, x2, x6); for(int l=0; l<1+vex.l; ++l) { if(!l) { GETEX_Y(v1, 0, 0); GETGX_empty(v0); + // after the address, so x2 can keep the old FPCR + u8 = sse_setround(dyn, ninst, x4, x5, x2); if(!BOX64ENV(dynarec_fastround) || vex.l) d0 = fpu_get_scratch(dyn, ninst); } else { diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c index 8454ea42c..12d7eacac 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c @@ -551,6 +551,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, } else { IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); for(int i=0; i<16; ++i) { VST1_8(v0, i, i?x1:wback); diff --git a/src/dynarec/arm64/dynarec_arm64_consts.c b/src/dynarec/arm64/dynarec_arm64_consts.c index c5e2ebacb..83ef32d3f 100644 --- a/src/dynarec/arm64/dynarec_arm64_consts.c +++ b/src/dynarec/arm64/dynarec_arm64_consts.c @@ -125,7 +125,7 @@ uintptr_t getConst(arm64_consts_t which) case const_fpu_xrstor: return (uintptr_t)fpu_xrstor; case const_fpu_fbld: return (uintptr_t)fpu_fbld; case const_fpu_fbst: return (uintptr_t)fpu_fbst; - case const_sse42_compare_string_explicit_len: return (uintptr_t)sse42_compare_string_explicit_len; + case const_sse42_compare_string_explicit_len: return (uintptr_t)sse42_compare_string_explicit_len_imm8w; case const_sse42_compare_string_implicit_len: return (uintptr_t)sse42_compare_string_implicit_len; case const_x64test_step: return (uintptr_t)x64test_step; case const_printtrace: return (uintptr_t)PrintTrace; diff --git a/src/dynarec/arm64/dynarec_arm64_d8.c b/src/dynarec/arm64/dynarec_arm64_d8.c index e2395358d..c0a6abe3a 100644 --- a/src/dynarec/arm64/dynarec_arm64_d8.c +++ b/src/dynarec/arm64/dynarec_arm64_d8.c @@ -63,7 +63,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -73,7 +73,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -101,7 +101,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -111,7 +111,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -176,7 +176,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -186,7 +186,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -214,7 +214,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -224,7 +224,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -252,7 +252,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -262,7 +262,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -290,7 +290,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -300,7 +300,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -328,7 +328,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -339,7 +339,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -362,7 +362,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -373,7 +373,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -425,7 +425,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -436,7 +436,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -459,7 +459,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -470,7 +470,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -493,7 +493,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -504,7 +504,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, s0); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -527,7 +527,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, s0, s5, s6); } } else { FCVT_D_S(s0, s0); @@ -538,7 +538,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, s0, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, s0, s5, s6); } } X87_CHECK_PRECISION(v1); diff --git a/src/dynarec/arm64/dynarec_arm64_da.c b/src/dynarec/arm64/dynarec_arm64_da.c index 8531c3f7b..9cd975af3 100644 --- a/src/dynarec/arm64/dynarec_arm64_da.c +++ b/src/dynarec/arm64/dynarec_arm64_da.c @@ -157,7 +157,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -180,7 +180,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -226,7 +226,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -249,7 +249,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -290,7 +290,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -313,7 +313,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) diff --git a/src/dynarec/arm64/dynarec_arm64_db.c b/src/dynarec/arm64/dynarec_arm64_db.c index fd4bda1bd..9f0f436ef 100644 --- a/src/dynarec/arm64/dynarec_arm64_db.c +++ b/src/dynarec/arm64/dynarec_arm64_db.c @@ -276,7 +276,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin NOTEST(x5); // the FLD is immediatly followed by an FSTP LDRx_U12(x5, ed, 0); - LDRH_U12(x6, ed, 8); + LDRH_U12(x4, ed, 8); // no persistant scratch register, so unrool both instruction here... MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n"); nextop = F8; // 0xDB or rex @@ -288,7 +288,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin nextop = F8; //modrm addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); STRx_U12(x5, ed, 0); - STRH_U12(x6, ed, 8); + STRH_U12(x4, ed, 8); } else { if(BOX64ENV(x87_no80bits)) { X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D); @@ -357,11 +357,21 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ORRx_mask(x5, x1, 1, 1, 0); //0x8000000000000000 x5 = mantisse B_MARK3_nocond; // denormals +#ifdef BOX64EC + // no x6 (guest R9) and x2 can be the address: x3 is free here (exp11 == 0), at the cost of the MOV + CLZx(x3, x1); + ADDw_U12(x3, x3, 1); // "one" + SUBw_REG(x4, x4, x3); // x4 = exp16 + ORRw_REG(x4, x4, x5); // x4 = sign | exp16 + LSLx_REG(x5, x1, x3); // x5 = mantisse + MOVw_REG(x3, x4); +#else CLZx(x6, x1); ADDw_U12(x6, x6, 1); // "one" SUBw_REG(x3, x4, x6); // x3 = exp16 ORRw_REG(x3, x3, x5); // x3 = sign | exp16 LSLx_REG(x5, x1, x6); // x5 = mantisse +#endif MARK3; STRx_U12(x5, wback, 0); STRH_U12(x3, wback, 8); diff --git a/src/dynarec/arm64/dynarec_arm64_dc.c b/src/dynarec/arm64/dynarec_arm64_dc.c index 07ff6a416..72f260358 100644 --- a/src/dynarec/arm64/dynarec_arm64_dc.c +++ b/src/dynarec/arm64/dynarec_arm64_dc.c @@ -59,7 +59,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -69,7 +69,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -97,7 +97,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -107,7 +107,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -172,7 +172,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -182,7 +182,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -210,7 +210,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -220,7 +220,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -248,7 +248,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -258,7 +258,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -286,7 +286,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -296,7 +296,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -323,7 +323,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -344,7 +344,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -384,7 +384,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -405,7 +405,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -426,7 +426,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -447,7 +447,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) diff --git a/src/dynarec/arm64/dynarec_arm64_de.c b/src/dynarec/arm64/dynarec_arm64_de.c index 6ee877134..f68dc2c35 100644 --- a/src/dynarec/arm64/dynarec_arm64_de.c +++ b/src/dynarec/arm64/dynarec_arm64_de.c @@ -59,7 +59,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -69,7 +69,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -98,7 +98,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -108,7 +108,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -169,7 +169,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -179,7 +179,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -208,7 +208,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -218,7 +218,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -247,7 +247,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -257,7 +257,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -286,7 +286,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVS(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_S(v1, s5, s6); + X87_ARITH_NAN_END_S(v1, v2, s5, s6); } } else { if(!BOX64ENV(dynarec_fastnan)) { @@ -296,7 +296,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } } X87_CHECK_PRECISION(v1); @@ -327,7 +327,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FADDD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -351,7 +351,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FMULD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -400,7 +400,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -424,7 +424,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FSUBD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -448,7 +448,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v1, v2); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) @@ -472,7 +472,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } FDIVD(v1, v2, v1); if(!BOX64ENV(dynarec_fastnan)) { - X87_ARITH_NAN_END_D(v1, s5, s6); + X87_ARITH_NAN_END_D(v1, v2, s5, s6); } X87_CHECK_PRECISION(v1); if(!BOX64ENV(dynarec_fastround)) diff --git a/src/dynarec/arm64/dynarec_arm64_emit_math.c b/src/dynarec/arm64/dynarec_arm64_emit_math.c index 10272f382..a2590d63b 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_math.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_math.c @@ -1001,9 +1001,13 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } } } else { - MRS_nzcv(s3); - BFIx(s3, xFlags, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, xFlags, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF) { ORRxw_REG(s3, s1, s2); // s3 = op1 | op2 @@ -1144,9 +1148,13 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } } else { - MRS_nzcv(s3); - BFIx(s3, xFlags, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, xFlags, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF | X_OF) { ORRw_REG(s3, s1, s2); // s3 = op1 | op2 @@ -1208,9 +1216,13 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } } else { - MRS_nzcv(s3); - BFIx(s3, xFlags, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(xFlags, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, xFlags, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF | X_OF) { ORRw_REG(s3, s1, s2); // s3 = op1 | op2 @@ -1332,9 +1344,13 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } } else { EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM - MRS_nzcv(s3); - BFIx(s3, s4, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(s4, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, s4, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF) { ORNxw_REG(s3, s2, s1); // s3 = ~op1 | op2 @@ -1481,9 +1497,13 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } else { EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM - MRS_nzcv(s3); - BFIx(s3, s4, 29, 1); // set C - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(s4, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, s4, 29, 1); // set C + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF|X_OF|X_CF) { ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2 @@ -1546,9 +1566,13 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } } else { EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM - MRS_nzcv(s3); - BFIx(s3, s4, 29, 1); // set C, bit 29 - MSR_nzcv(s3); // load CC into ARM CF + if(cpuext.flagm) + RMIF(s4, 63, 0b0010); + else { + MRS_nzcv(s3); + BFIx(s3, s4, 29, 1); // set C, bit 29 + MSR_nzcv(s3); // load CC into ARM CF + } } IFX(X_AF|X_OF|X_CF) { ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2 diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index b5b15abf4..580d9c9b8 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1275,9 +1275,14 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i } // emit RCL32/RCL64 instruction, from s1 , shift s2 (destroyed), store result in s1 using s3 and s4 as scratch -void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); +#ifdef BOX64EC + int s5 = s3; // no x6 (guest R9), so s3 is reused and the new CF waits in F_res2 +#else + int s5 = x6; +#endif if(BOX64ENV(cputype)) { IFX(X_OF|X_CF) { @@ -1292,6 +1297,11 @@ void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 LSRxw_REG(s3, s1, s4); } } +#ifdef BOX64EC + IFX(BOX64ENV(cputype)?(X_OF|X_CF):X_CF) { + BFIw(xFlags, s3, F_res2, 1); + } +#endif if(!BOX64ENV(cputype)) IFX(X_OF) { LSRxw(s4, s1, rex.w?62:30); @@ -1319,15 +1329,27 @@ void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 ORRxw_REG(s1, s1, s4); } IFX(X_CF) { +#ifdef BOX64EC + BFXILw(xFlags, xFlags, F_res2, 1); +#else BFIw(xFlags, s3, F_CF, 1); +#endif } IFX2(X_OF, && BOX64ENV(cputype)) { +#ifdef BOX64EC + UBFXw(s3, xFlags, F_res2, 1); +#endif EORxw_REG_LSR(s3, s3, s1, rex.w?63:31); BFIw(xFlags, s3, F_OF, 1); } +#ifdef BOX64EC + IFX(BOX64ENV(cputype)?(X_OF|X_CF):X_CF) { + BFCw(xFlags, F_res2, 1); + } +#endif } -// emit RCR32/RCR64 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch -void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +// emit RCR32/RCR64 instruction, from s1 , shift s2 (destroyed), store result in s1 using s3 and s4 as scratch +void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); @@ -1349,15 +1371,15 @@ void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } /*else*/ { - LSRxw_REG(s5, s1, s2); - UBFXw(s4, xFlags, 0, 1); + LSRxw_REG(s4, s1, s2); MOVZw(s3, (rex.w?64:32)); SUBx_REG(s3, s3, s2); - LSLxw_REG(s4, s4, s3); - ORRxw_REG(s5, s5, s4); + UBFXw(s2, xFlags, 0, 1); // s2 is not needed anymore + LSLxw_REG(s2, s2, s3); + ORRxw_REG(s4, s4, s2); ADDx_U12(s3, s3, 1); LSLxw_REG(s1, s1, s3); - ORRxw_REG(s1, s1, s5); + ORRxw_REG(s1, s1, s4); } IFX(X_CF) { BFXILw(xFlags, xFlags, F_res2, 1); @@ -1623,8 +1645,9 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int c&=0x1f; IFX(X_PEND) { MOV32w(s3, c); + ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, the deferred handler needs it for OF + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shrd16); } else { SET_DFNONE(); @@ -1666,7 +1689,8 @@ void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, { IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s5, xEmu, offsetof(x64emu_t, op2)); + ORRw_REG_LSL(s3, s5, s2, 16); // store fill in the upper half, needed for count > 16 + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); // same flags computation as with shl64/shl32 SET_DF(s4, d_shrd16); } else { @@ -1715,8 +1739,9 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int c&=0x1f; IFX(X_PEND) { MOV32w(s3, c); + ORRw_REG_LSL(s3, s3, s2, 16); // store fill in the upper half, the deferred handler needs it for OF + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else { SET_DFNONE(); @@ -1770,7 +1795,8 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, { IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); - STRH_U12(s5, xEmu, offsetof(x64emu_t, op2)); + ORRw_REG_LSL(s3, s5, s2, 16); // store fill in the upper half, needed for count > 16 + STRw_U12(s3, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else { SET_DFNONE(); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_tests.c b/src/dynarec/arm64/dynarec_arm64_emit_tests.c index f74c201d7..03887a719 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_tests.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_tests.c @@ -310,8 +310,8 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) } } -// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s2); MAYUSE(s3); MAYUSE(s4); IFX_PENDOR0 { @@ -349,12 +349,12 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } } IFX(X_PF) { - emit_pf(dyn, ninst, s3, s5); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5) +// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); int mask = convert_bitmask_xw(c); @@ -398,12 +398,12 @@ void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } } IFX(X_PF) { - emit_pf(dyn, ninst, s3, s5); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +// emit TEST16 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s2); IFX_PENDOR0 { @@ -412,8 +412,8 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 16); - ANDSw_REG_LSL(s5, s5, s2, 16); + LSLw(s3, s1, 16); + ANDSw_REG_LSL(s3, s3, s2, 16); IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { CSETw(s4, cEQ); @@ -433,24 +433,24 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 16); + LSRw(s3, s3, 16); } } else { - ANDw_REG(s5, s1, s2); // res = s1 & s2 + ANDw_REG(s3, s1, s2); // res = s1 & s2 } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRH_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5) +// emit TEST16 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); int mask = 0; @@ -460,13 +460,13 @@ void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 16); + LSLw(s3, s1, 16); mask = convert_bitmask_w(c<<16); if(mask) { - ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F); + ANDSw_mask(s3, s3, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s3, c); - ANDSw_REG_LSL(s5, s5, s3, 16); + MOV32w(s4, c); + ANDSw_REG_LSL(s3, s3, s4, 16); } IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { @@ -487,30 +487,30 @@ void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 16); + LSRw(s3, s3, 16); } } else { mask = convert_bitmask_w(c); if(mask) { - ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F); + ANDw_mask(s3, s1, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s5, c); - ANDw_REG(s5, s1, s5); // res = s1 & s2 + MOV32w(s3, c); + ANDw_REG(s3, s1, s3); // res = s1 & s2 } } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRH_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRH_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } -// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +// emit TEST8 instruction, from test s1, s2, using s3 and s4 as scratch +void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) { MAYUSE(s1); MAYUSE(s2); IFX_PENDOR0 { @@ -519,8 +519,8 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 24); - ANDSw_REG_LSL(s5, s5, s2, 24); + LSLw(s3, s1, 24); + ANDSw_REG_LSL(s3, s3, s2, 24); IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { CSETw(s4, cEQ); @@ -540,24 +540,24 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 24); + LSRw(s3, s3, 24); } } else { - ANDw_REG(s5, s1, s2); // res = s1 & s2 + ANDw_REG(s3, s1, s2); // res = s1 & s2 } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRB_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRB_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } // emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch -void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5) +void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); int mask = 0; @@ -567,13 +567,13 @@ void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int SET_DFNONE(); } IFX(X_CF|X_ZF|X_SF|X_OF) { - LSLw(s5, s1, 24); + LSLw(s3, s1, 24); mask = convert_bitmask_w(c<<24); if(mask) { - ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F); + ANDSw_mask(s3, s3, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s3, c); - ANDSw_REG_LSL(s5, s5, s3, 24); + MOV32w(s4, c); + ANDSw_REG_LSL(s3, s3, s4, 24); } IFX(X_ZF) { IFNATIVE(NF_EQ) {} else { @@ -594,24 +594,24 @@ void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } } IFX(X_PF|X_PEND) { - LSRw(s5, s5, 24); + LSRw(s3, s3, 24); } } else { mask = convert_bitmask_w(c); if(mask) { - ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F); + ANDw_mask(s3, s1, mask&0x3F, (mask>>6)&0x3F); } else { - MOV32w(s5, c); - ANDw_REG(s5, s1, s5); // res = s1 & s2 + MOV32w(s3, c); + ANDw_REG(s3, s1, s3); // res = s1 & s2 } } IFX(X_AF) { BFCw(xFlags, F_AF, 1); } IFX_PENDOR0 { - STRB_U12(s5, xEmu, offsetof(x64emu_t, res)); + STRB_U12(s3, xEmu, offsetof(x64emu_t, res)); } IFX(X_PF) { - emit_pf(dyn, ninst, s5, s4); + emit_pf(dyn, ninst, s3, s4); } } diff --git a/src/dynarec/arm64/dynarec_arm64_f0.c b/src/dynarec/arm64/dynarec_arm64_f0.c index 40d84d67e..8470c1542 100644 --- a/src/dynarec/arm64/dynarec_arm64_f0.c +++ b/src/dynarec/arm64/dynarec_arm64_f0.c @@ -239,28 +239,28 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("LOCK CMPXCHG Eb, Gb"); SETFLAGS(X_ALL, SF_SET_PENDING); GETGB(x1); - UBFXx(x6, xRAX, 0, 8); + UBFXx(x5, xRAX, 0, 8); addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); if(cpuext.atomics) { UFLAG_IF { - MOVw_REG(x2, x6); - CASALB(x6, gd, wback); - emit_cmp8(dyn, ninst, x2, x6, x3, x4, x5); + MOVw_REG(x2, x5); + CASALB(x5, gd, wback); + emit_cmp8(dyn, ninst, x2, x5, x3, x4, x1); } else { - CASALB(x6, gd, wback); + CASALB(x5, gd, wback); } - BFIx(xRAX, x6, 0, 8); + BFIx(xRAX, x5, 0, 8); } else { MARKLOCK; LDAXRB(x2, wback); - CMPSxw_REG(x6, x2); + CMPSxw_REG(x5, x2); B_MARK(cNE); // EAX == Ed STLXRB(x4, gd, wback); CBNZx_MARKLOCK(x4); // done MARK; - UFLAG_IF {emit_cmp8(dyn, ninst, x6, x2, x3, x4, x5);} + UFLAG_IF {emit_cmp8(dyn, ninst, x5, x2, x3, x4, x1);} BFIx(xRAX, x2, 0, 8); } } @@ -283,7 +283,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - UFLAG_IF { MOVxw_REG(x6, xRAX); } + UFLAG_IF { MOVxw_REG(x5, xRAX); } if(!ALIGNED_ATOMICxw) { if(cpuext.uscat) { ANDx_mask(x1, wback, 1, 0, 3); // mask = F @@ -345,7 +345,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } MARK; UFLAG_IF { - emit_cmp32(dyn, ninst, rex, x6, x1, x3, x4, x5); + emit_cmp32(dyn, ninst, rex, x5, x1, x3, x4, x2); } } break; @@ -823,11 +823,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETGB(x2); addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRB(x1, wback); emit_adc8(dyn, ninst, x1, x2, x4, x5); STLXRB(x4, x1, wback); @@ -848,11 +844,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRxw(x1, wback); emit_adc32(dyn, ninst, rex, x1, gd, x4, x5); STLXRxw(x4, x1, wback); @@ -1107,11 +1099,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1); u8 = F8; wb1 = 1; - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRB(x1, wback); emit_adc8c(dyn, ninst, x1, u8, x2, x4, x3); STLXRB(x3, x1, wback); @@ -1132,11 +1120,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1); u8 = F8; wb1 = 1; - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRB(x1, wback); emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x3); STLXRB(x3, x1, wback); @@ -1369,11 +1353,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1); if(opcode==0x81) i64 = F32S; else i64 = F8S; MOV64xw(x5, i64); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRxw(x1, wback); emit_adc32(dyn, ninst, rex, x1, x5, x3, x4); STLXRxw(x3, x1, wback); @@ -1394,11 +1374,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1); if(opcode==0x81) i64 = F32S; else i64 = F8S; MOV64xw(x5, i64); - MOVx_REG(x6, xFlags); - MRS_nzcv(x87pc); - MARKLOCK; - MOVx_REG(xFlags, x6); - MSR_nzcv(x87pc); + MARKLOCK_SAVE_FLAGS(); LDAXRxw(x1, wback); emit_sbb32(dyn, ninst, rex, x1, x5, x3, x4); STLXRxw(x3, x1, wback); diff --git a/src/dynarec/arm64/dynarec_arm64_f30f.c b/src/dynarec/arm64/dynarec_arm64_f30f.c index 9ba5e34d1..549197aed 100644 --- a/src/dynarec/arm64/dynarec_arm64_f30f.c +++ b/src/dynarec/arm64/dynarec_arm64_f30f.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #include #include @@ -591,6 +591,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } else { IF_UNALIGNED(ip) { MESSAGE(LOG_DEBUG, "\tUnaligned path"); + NOLRCPC(); addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); for(int i=0; i<16; ++i) { VST1_8(v0, i, i?x1:wback); diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c index 271391e82..e61a44452 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.c +++ b/src/dynarec/arm64/dynarec_arm64_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -767,8 +766,8 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r return; } - static char buf[4096]; - int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%c, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)", + static char buf[8192]; + int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%c, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)%d", dyn->insts[ninst].x64.barrier, dyn->insts[ninst].x64.state_flags, df_status[dyn->f], @@ -780,7 +779,11 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r dyn->insts[ninst].x64.use_flags, dyn->insts[ninst].x64.need_before, dyn->insts[ninst].x64.need_after, - dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write, dyn->insts[ninst].lock); + dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write, dyn->insts[ninst].lock, + dyn->insts[ninst].x64.strongmem); + if(dyn->insts[ninst].use_lrcpc || dyn->insts[ninst].has_lrcpc) { + length += sprintf(buf + length, " LRCPC:%d/%d", dyn->insts[ninst].use_lrcpc, dyn->insts[ninst].has_lrcpc); + } if (dyn->insts[ninst].nat_flags_op) { if (dyn->insts[ninst].nat_flags_op == NAT_FLAG_OP_TOUCH && dyn->insts[ninst].before_nat_flags) length += sprintf(buf + length, " NF:%d/read:%x", dyn->insts[ninst].nat_flags_op, dyn->insts[ninst].before_nat_flags); @@ -1510,6 +1513,11 @@ void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached) } +void sse_mark_used(dynarec_arm_t* dyn, int ninst, int a) +{ + dyn->n.xmm_used |= 1<insts[i2-1].x64.has_next) // need a previous opcode to set the preload, unless it's the #0 return; // check if there is jump out or outside this loop + int has_host_call = 0; for(int i=i2; iinsts[i].x64.has_next || (dyn->insts[i].x64.barrier&BARRIER_FLOAT)) return; // for now, unneeded stop at first jump, so this should also stop there if(dyn->insts[i].x64.jmp/* && ((dyn->insts[i].x64.jmp_insts>ninst) || (dyn->insts[i].x64.jmp_instsinsts[i].host_call_clobber) + return; + if(dyn->insts[i].host_call) + has_host_call = 1; } uint16_t ymm_mask = 0; for(int i=0; i<16; ++i) { @@ -1613,9 +1626,9 @@ void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload) } } preload = (preload&0xffff) | (ymm_mask<<16); // update ymm_mask - //TODO: should check native calls too? dyn->insts[i2].preload_xmmymm = preload; dyn->insts[i2].preload_from = ninst; + dyn->insts[i2].preload_host_call = has_host_call; dyn->insts[i2].n.xmm_unneeded |= preload&0xffff; dyn->insts[i2].n.ymm_unneeded |= ymm_mask; } diff --git a/src/dynarec/arm64/dynarec_arm64_functions.h b/src/dynarec/arm64/dynarec_arm64_functions.h index 3d0f01cd0..03c66c479 100644 --- a/src/dynarec/arm64/dynarec_arm64_functions.h +++ b/src/dynarec/arm64/dynarec_arm64_functions.h @@ -93,6 +93,9 @@ void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached); // add a preload of SSE/AVX register preload before i2, for a jump in ninst. Might not do it if there is jump in between that goes outside this ninst-i2 interval void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload); +// mark a SSE reg as read by the current opcode, without touching its cache entry +void sse_mark_used(dynarec_arm_t* dyn, int ninst, int a); + // AVX helpers void avx_mark_zero(dynarec_arm_t* dyn, int ninst, int reg); int is_avx_zero(dynarec_arm_t* dyn, int ninst, int reg); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 92f455fc7..3ed5deb79 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -35,6 +35,12 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u int lock = l?((l==LOCK_LOCK)?1:2):0; if(lock==2) *l = 0; + if(dyn->insts[ninst].use_lrcpc) { + if(!unscaled) { + NOLRCPC(); + } else { absmax = 0; mask=0;} + } // there is no "Scaled" version, only Unscaled + if(rex.is32bits && rex.is67) return geted16(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, rex, s); @@ -44,7 +50,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u uint8_t scratch = x2; *fixaddress = 0; if(hint>0) ret = hint; - if(hint>0 && hint0 && !IS_GPR(hint)) scratch = hint; int absmin = 0; if(s) absmin=-absmax; int seg_done = 0; @@ -198,7 +204,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u } ADDy_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6)); } else { - PASS3(int tmp = TO_NAT(sib & 0x07) + (rex.b << 3)); + PASS3(int tmp = TO_NAT((sib & 0x07) + (rex.b << 3))); if(sub) { SUBy_REG(ret, tmp, scratch); } else { @@ -221,8 +227,9 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u ret = hint; } if(rex.seg && !seg_done) { + scratch = (hint>0 && !IS_GPR(hint)) ? hint : x2; if(scratch==ret) - scratch=ret+1; + scratch = xLR; // dead between opcodes, ret+1 can be a guest register grab_segdata(dyn, addr, ninst, scratch, rex.seg); //seg offset is 64bits, so no truncation here ADDx_REGy(hint, scratch, ret); @@ -314,7 +321,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if(rex.seg) { if(scratch==ret) - scratch=ret+1; + scratch = xLR; grab_segdata(dyn, addr, ninst, scratch, rex.seg); //seg offset is 64bits, so no truncation here if(IS_GPR(ret)) { @@ -343,8 +350,10 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) +#ifndef BOX64EC // no CALLRET on Box64EC yet + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); +#endif BR(x2); } @@ -419,8 +428,10 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 if(reg!=x1) { MOVx_REG(x1, xRIP); } - if(BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) +#ifndef BOX64EC // no CALLRET on Box64EC yet + if(BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); +#endif // #ifdef HAVE_TRACE // The BLR form is only for gdb backtraces, but it breaks the // return-address-stack prediction on every block-to-block jump, which is @@ -441,17 +452,19 @@ void ret_to_next(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) CHECK_DFNONE(0); MOVz_REG(x1, xRIP); SMEND(); +#ifndef BOX64EC // no CALLRET on Box64EC yet if(BOX64DRENV(dynarec_callret)) { // pop the actual return address for ARM stack LDPx_S7_postindex(xLR, x6, xSP, 16); SUBx_REG(x6, x6, xRIP); // is it the right address? - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x3); CBNZx(x6, 2*4); RET(xLR); // not the correct return address, regular jump, but purge the stack first, it's unsync now... SUBx_U12(xSP, xSavedSP, 16); } +#endif NOTEST(x2); int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3); #ifdef HAVE_TRACE @@ -542,6 +555,7 @@ void iret_to_next(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, int void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, int saveflags, int savereg) { MAYUSE(fnc); + dyn->insts[ninst].host_call = 1; CHECK_DFNONE(1); #if STEP == 0 dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE; @@ -558,12 +572,16 @@ void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP])); STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI])); STPx_S7_offset(xR8, xR9, xEmu, offsetof(x64emu_t, regs[_R8])); +#ifdef BOX64EC + // R10 and R11 are not preserved by the C call in the EC map + STPx_S7_offset(xR10, xR11, xEmu, offsetof(x64emu_t, regs[_R10])); +#endif fpu_pushcache(dyn, ninst, savereg, 0); for(int i=0; in.fpu_scratch; ++i) VSTR128_S9_preindex(SCRATCH0+i, xSP, -16); } #ifdef _WIN32 - LDRx_U12(xR8, xEmu, offsetof(x64emu_t, win64_teb)); + LDRx_U12(xTEB, xEmu, offsetof(x64emu_t, win64_teb)); #endif TABLE64C(reg, fnc); BLR(reg); @@ -586,21 +604,30 @@ void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, GO(RSP, RBP); GO(RSI, RDI); GO(R8, R9); +#ifdef BOX64EC + GO(R10, R11); +#endif #undef GO fpu_popcache(dyn, ninst, savereg, 0); // savereg will not be used } if(saveflags) { LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); } +#ifdef BOX64EC + // x87pc is x5, the pop above restored an argument: reload it + NATIVE_RESTORE_X87PC(); +#else if(savereg!=x87pc && dyn->need_x87check) { NATIVE_RESTORE_X87PC(); } +#endif //SET_NODF(); } void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1, int arg2, int sav1, int sav2) { MAYUSE(fnc); + dyn->insts[ninst].host_call = 1; CHECK_DFNONE(1); #if STEP == 0 dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE; @@ -614,11 +641,14 @@ void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1 STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP])); STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI])); STPx_S7_offset(xR8, xR9, xEmu, offsetof(x64emu_t, regs[_R8])); +#ifdef BOX64EC + STPx_S7_offset(xR10, xR11, xEmu, offsetof(x64emu_t, regs[_R10])); // not preserved by the C call, as in call_c +#endif STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); fpu_pushcache(dyn, ninst, x87pc, 0); #ifdef _WIN32 - LDRx_U12(xR8, xEmu, offsetof(x64emu_t, win64_teb)); + LDRx_U12(xTEB, xEmu, offsetof(x64emu_t, win64_teb)); #endif if(arg1!=-1) FMOVD(0, arg1); @@ -638,6 +668,9 @@ void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1 GO(RSP, RBP); GO(RSI, RDI); GO(R8, R9); +#ifdef BOX64EC + GO(R10, R11); +#endif #undef GO LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); fpu_popcache(dyn, ninst, x1, 0); // savereg will not be used @@ -647,6 +680,8 @@ void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1 void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w) { MAYUSE(fnc); + dyn->insts[ninst].host_call = 1; + dyn->insts[ninst].host_call_clobber = 1; CHECK_DFNONE(1); #if STEP == 0 dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE; @@ -1542,8 +1577,9 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a) dyn->n.xmm_used |= 1<n.ssecache[a].reg; } + if(!(dyn->n.xmm_used&(1<n.xmm_unneeded |= 1<n.xmm_used |= 1<n.xmm_unneeded |= 1<n.ssecache[a].reg = fpu_get_reg_xmm(dyn, NEON_CACHE_XMMW, a); dyn->n.ssecache[a].write = 1; // it will be write... return dyn->n.ssecache[a].reg; @@ -1552,10 +1588,13 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a) void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a) { dyn->n.xmm_used |= 1<n.ssecache[a].v==-1) - return; - if(dyn->n.neoncache[dyn->n.ssecache[a].reg].t == NEON_CACHE_XMMW) { - VSTR128_U12(dyn->n.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); + dyn->n.ymm_used |= 1<n.ssecache[a].v!=-1) { + if(dyn->n.neoncache[dyn->n.ssecache[a].reg].t == NEON_CACHE_XMMW) { + VSTR128_U12(dyn->n.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); + } + fpu_free_reg(dyn, dyn->n.ssecache[a].reg); + dyn->n.ssecache[a].v = -1; } // YMM part too if(is_avx_zero_unset(dyn, ninst, a)) { @@ -1573,9 +1612,6 @@ void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a) fpu_free_reg(dyn, i); } - fpu_free_reg(dyn, dyn->n.ssecache[a].reg); - dyn->n.ssecache[a].v = -1; - return; } // purge the SSE cache for XMM0..XMM7 (to use before function native call) void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1) @@ -2122,6 +2158,8 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int MESSAGE(LOG_DUMP, "\tFPU Cache Transform ---- ninst=%d -> %d\n", ninst, i2); uint32_t unneeded = dyn->insts[i2].n.xmm_unneeded | (dyn->insts[i2].n.ymm_unneeded<<16); if((!i2) || (dyn->insts[i2].x64.barrier&BARRIER_FLOAT)) { + if(dyn->insts[i2].preload_host_call) + unneeded &= ~dyn->insts[i2].preload_xmmymm; int need_purge = 0; if(dyn->n.stack_next) need_purge = 1; @@ -2265,9 +2303,9 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int } } } - if(stack_cnt != cache_i2.stack) { - MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack); - int a = stack_cnt - cache_i2.stack; + if(stack_cnt != cache_i2.stack || dyn->n.x87stack != cache_i2.x87stack) { + MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d / pending %d -> %d -\n", stack_cnt, cache_i2.stack, dyn->n.x87stack, cache_i2.x87stack); + int a = dyn->n.x87stack - cache_i2.x87stack; // Add x87stack to emu fpu_stack LDRw_U12(s3, xEmu, offsetof(x64emu_t, fpu_stack)); if(a>0) { @@ -2341,12 +2379,25 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst) j64 = (GETMARKF2)-(dyn->native_size); CBZw(x1, j64); } - if(dyn->insts[ninst].need_nat_flags) + if(dyn->insts[ninst].need_nat_flags) { +#ifdef BOX64EC + // updateflags uses x1 to x5 and x6 is guest R9: NZCV goes through the emu + MRS_nzcv(x1); + STRx_U12(x1, xEmu, offsetof(x64emu_t, scratch[0])); +#else MRS_nzcv(x6); +#endif + } TABLE64C(x1, const_updateflags_arm64); BLR(x1); - if(dyn->insts[ninst].need_nat_flags) + if(dyn->insts[ninst].need_nat_flags) { +#ifdef BOX64EC + LDRx_U12(x1, xEmu, offsetof(x64emu_t, scratch[0])); + MSR_nzcv(x1); +#else MSR_nzcv(x6); +#endif + } MARKF2; } MESSAGE(LOG_DUMP, "\t---- Flags fetch\n"); @@ -2971,8 +3022,8 @@ void checkCRC(dynarec_arm_t* dyn, int ninst) // grab the dynablock address in x5, as this on will not be erased by crc functions int delta = -(dyn->native_size + sizeof(void*)); LDRx_literal(x5, delta); - // move away xEMU to X6, should be safe there - MOVx_REG(x6, xEmu); + // move away xEMU to the stack, x6 is guest R9 on Box64EC + STPx_S7_preindex(xEmu, xZR, xSP, -16); // prepare and call the crc function TABLE64C(x3, cpuext.crc32?const_native_crc32:const_native_x31); LDRx_U12(xEmu, x5, offsetof(dynablock_t, x64_addr)); @@ -2980,10 +3031,14 @@ void checkCRC(dynarec_arm_t* dyn, int ninst) BLR(x3); // done, move away result and restore xEmu MOVw_REG(x1, xEmu); - MOVx_REG(xEmu, x6); + LDPx_S7_postindex(xEmu, xZR, xSP, 16); LDRw_U12(x2, x5, offsetof(dynablock_t, hash)); SUBw_REG(x1, x1, x2); CBZw(x1, 4+2*4); TABLE64C(x3, const_native_next_invalidate); BLR(x3); +#ifdef BOX64EC + // x5 held the dynablock, which is x87pc here + NATIVE_RESTORE_X87PC(); +#endif } diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index b44334bdf..191aac020 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -40,6 +40,9 @@ #ifndef FEMIT #define FEMIT(A) EMIT(A) #endif +#ifndef LEMIT +#define LEMIT(A) EMIT(A) +#endif #ifndef ENDPREFIX #define ENDPREFIX #endif @@ -575,15 +578,15 @@ #define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress&(((1<<(2+rex.w))-1)))) || BOX64ENV(dynarec_aligned_atomics)) #define ALIGNED_ATOMICH ((fixedaddress && !(fixedaddress&1)) || BOX64ENV(dynarec_aligned_atomics)) -// CALL will use x7 for the call address. Return value can be put in ret (unless ret is -1) +// CALL will use xLR for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2 -#define CALL(F, ret) call_c(dyn, ninst, F, x87pc, ret, 1, 0) -// CALL_ will use x7 for the call address. Return value can be put in ret (unless ret is -1) +#define CALL(F, ret) call_c(dyn, ninst, F, xLR, ret, 1, 0) +// CALL_ will use xLR for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2 -#define CALL_(F, ret, reg) call_c(dyn, ninst, F, x87pc, ret, 1, reg) -// CALL_S will use x7 for the call address. Return value can be put in ret (unless ret is -1) +#define CALL_(F, ret, reg) call_c(dyn, ninst, F, xLR, ret, 1, reg) +// CALL_S will use xLR for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2. Flags are not save/restored -#define CALL_S(F, ret) call_c(dyn, ninst, F, x87pc, ret, 0, 0) +#define CALL_S(F, ret) call_c(dyn, ninst, F, xLR, ret, 0, 0) // CALL_D will use x7 for the call address. Use for function having 1 or 2 double args and returning 1 double // All regs are saved, including xmm0-7, will move arg1/arg2 to D0, D1, return D0 to ret (unless any is -1) #define CALL_D(F, ret, arg1, arg2, sav1, sav2) call_d(dyn, ninst, F, ret, arg1, arg2, sav1, sav2) @@ -601,6 +604,26 @@ #define MARKSEG dyn->insts[ninst].markseg = dyn->native_size #define GETMARKSEG dyn->insts[ninst].markseg #define MARKLOCK dyn->insts[ninst].marklock = dyn->native_size +#ifdef BOX64EC +// x6 is guest R9 and x87pc is x5, so keep the flags in the emu across the retry loop +#define MARKLOCK_SAVE_FLAGS() do { \ + STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \ + MRS_nzcv(x4); \ + STRx_U12(x4, xEmu, offsetof(x64emu_t, scratch[0])); \ + MARKLOCK; \ + LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \ + LDRx_U12(x4, xEmu, offsetof(x64emu_t, scratch[0])); \ + MSR_nzcv(x4); \ +} while (0) +#else +#define MARKLOCK_SAVE_FLAGS() do { \ + MOVx_REG(x6, xFlags); \ + MRS_nzcv(x87pc); \ + MARKLOCK; \ + MOVx_REG(xFlags, x6); \ + MSR_nzcv(x87pc); \ +} while (0) +#endif #define GETMARKLOCK dyn->insts[ninst].marklock // Branch to MARK if cond (use j64) @@ -861,11 +884,22 @@ #endif #ifndef X87_ARITH_NAN_END_D -#define X87_ARITH_NAN_END_D(vres, tmp, tmp2) \ +#define X87_ARITH_NAN_END_D(vres, vb, tmp, tmp2) \ FCMEQD(tmp2, vres, vres); \ - VBIC(tmp, tmp, tmp2); \ - VSHLQ_64(tmp, tmp, 63); \ - VORR(vres, vres, tmp) + VBIC(tmp2, tmp, tmp2); \ + VSHLQ_64(tmp2, tmp2, 63); \ + VORR(vres, vres, tmp2); \ + VSSHRQ_64(tmp2, vres, 63); \ + FCMEQD(tmp, vres, vres); \ + VMVNQ(tmp, tmp); \ + VANDQ(tmp, tmp, tmp2); \ + VSSHRQ_64(tmp2, vb, 63); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + FCMEQD(tmp2, vb, vb); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + VBIT(vres, vb, tmp) #endif #ifndef X87_ARITH_NAN_START_S @@ -875,11 +909,22 @@ #endif #ifndef X87_ARITH_NAN_END_S -#define X87_ARITH_NAN_END_S(vres, tmp, tmp2) \ +#define X87_ARITH_NAN_END_S(vres, vb, tmp, tmp2) \ FCMEQS(tmp2, vres, vres); \ - VBIC(tmp, tmp, tmp2); \ - VSHL_32(tmp, tmp, 31); \ - VORR(vres, vres, tmp) + VBIC(tmp2, tmp, tmp2); \ + VSHL_32(tmp2, tmp2, 31); \ + VORR(vres, vres, tmp2); \ + VSSHR_32(tmp2, vres, 31); \ + FCMEQS(tmp, vres, vres); \ + VMVNQ(tmp, tmp); \ + VANDQ(tmp, tmp, tmp2); \ + VSSHR_32(tmp2, vb, 31); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + FCMEQS(tmp2, vb, vb); \ + VMVNQ(tmp2, tmp2); \ + VANDQ(tmp, tmp, tmp2); \ + VBIT(vres, vb, tmp) #endif #define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A])) @@ -1004,8 +1049,8 @@ #define READFLAGS(A) \ if((A)!=X_PEND \ && (dyn->f==status_unk)) { \ - TABLE64C(x6, const_updateflags_arm64); \ - BLR(x6); \ + TABLE64C(x5, const_updateflags_arm64); \ + BLR(x5); \ dyn->f = status_none; \ } else if((A)==X_ALL) flushNative(dyn, ninst); #endif @@ -1013,8 +1058,8 @@ #define GRABFLAGS(A) \ if((A)!=X_PEND \ && ((dyn->f==status_unk) || (dyn->f==status_set))) { \ - TABLE64C(x6, const_updateflags_arm64); \ - BLR(x6); \ + TABLE64C(x5, const_updateflags_arm64); \ + BLR(x5); \ dyn->f = status_none; \ } @@ -1371,12 +1416,12 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); -void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); -void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5); -void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); -void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5); -void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); -void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); +void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); +void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); +void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); +void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); +void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5); void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4); @@ -1458,8 +1503,8 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); -void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); -void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); +void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); +void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4); diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h index 4b6283583..2f194e72a 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass0.h +++ b/src/dynarec/arm64/dynarec_arm64_pass0.h @@ -38,7 +38,11 @@ dyn->n.combined1 = dyn->n.combined2 = 0;\ dyn->n.swapped = 0; dyn->n.barrier = 0; \ dyn->insts[ninst].f_entry = dyn->f; \ - if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ + dyn->insts[ninst].host_call = 0; \ + dyn->insts[ninst].host_call_clobber = 0;\ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)); \ + if(dyn->insts[ninst].x64.strongmem && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) dyn->insts[ninst].use_lrcpc = 1; \ + if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ AREFLAGSNEEDED() #define INST_EPILOG \ @@ -46,7 +50,11 @@ dyn->insts[ninst].n = dyn->n; \ if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && !dyn->insts[ninst].set_nat_flags) \ dyn->insts[ninst].nat_flags_op=NAT_FLAG_OP_UNUSABLE; \ - dyn->insts[ninst].x64.has_next = (ok>0)?1:0; + dyn->insts[ninst].x64.has_next = (ok>0)?1:0; \ + if(dyn->insts[ninst].use_lrcpc && (!dyn->insts[ninst].has_lrcpc || is_addr_lrcpc(ip))) \ + dyn->insts[ninst].use_lrcpc = 0; \ + if(dyn->insts[ninst].x64.strongmem && dyn->insts[ninst].use_lrcpc) dyn->insts[ninst].x64.strongmem = 0 + #define INST_NAME(name) #define DEFAULT \ --dyn->size; \ @@ -58,7 +66,8 @@ } -#define FEMIT(A) dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].x64.set_flags?NAT_FLAG_OP_TOUCH:NAT_FLAG_OP_UNUSABLE +#define FEMIT(A) do {dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].x64.set_flags?NAT_FLAG_OP_TOUCH:NAT_FLAG_OP_UNUSABLE; EMIT(A);} while(0) +#define LEMIT(A) do {dyn->insts[ninst].has_lrcpc = 1; EMIT(A);} while(0) #define IFNATIVE(A) if(mark_natflag(dyn, ninst, A, 0)) #define IFNATIVEN(A) if(mark_natflag(dyn, ninst, A, 0)) #define UFLAG_IF if(dyn->insts[ninst].x64.set_flags) diff --git a/src/dynarec/arm64/dynarec_arm64_pass1.h b/src/dynarec/arm64/dynarec_arm64_pass1.h index 8b468966e..6368d1b7d 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass1.h +++ b/src/dynarec/arm64/dynarec_arm64_pass1.h @@ -3,6 +3,7 @@ #define FINI #define MESSAGE(A, ...) do {} while (0) #define EMIT(A) do {} while (0) +#define LEMIT(A) do {dyn->insts[ninst].has_lrcpc = 1; EMIT(A);} while(0) // do not update dyn->f for SETFLAGS(..., SF_SET_PENDING) because it will use either DF_NONE or DF_SET anyway (similar to SF_SET_NODF) #define SETFLAGS(A,B) \ @@ -20,7 +21,9 @@ #define INST_EPILOG \ dyn->insts[ninst].n = dyn->n; \ - dyn->insts[ninst].f_exit = dyn->f + dyn->insts[ninst].f_exit = dyn->f; \ + if(dyn->insts[ninst].use_lrcpc && (!dyn->insts[ninst].has_lrcpc || is_addr_lrcpc(ip))) \ + dyn->insts[ninst].use_lrcpc = 0 #define INST_NAME(name) diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index 772723ef2..3df190d9a 100644 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -156,6 +156,11 @@ typedef struct instruction_arm64_s { unsigned x87_used:1; // no fine tracking, just a global "any reg used" unsigned fpu_used:1; // any xmm/ymm/x87/mmx reg used unsigned fpupurge:1; // this opcode will purge all fpu regs + unsigned host_call:1; // this opcode performs a native call + unsigned host_call_clobber:1; // native call does not preserve cached xmm0-7 (call_n) + unsigned preload_host_call:1; // preload range contains a host call, needs write-back at merge + unsigned use_lrcpc:1;// use the various lrcpc opcode here instead of regular LD/ST + memory barrier + unsigned has_lrcpc:1;// set if the opcode has some lrcpc opcode in it flagcache_t f_exit; // flags status at end of instruction neoncache_t n; // neoncache at end of instruction (but before poping) flagcache_t f_entry; // flags status before the instruction begin diff --git a/src/dynarec/arm64/updateflags_arm64_pass.c b/src/dynarec/arm64/updateflags_arm64_pass.c index b770173ef..a07b1dc09 100644 --- a/src/dynarec/arm64/updateflags_arm64_pass.c +++ b/src/dynarec/arm64/updateflags_arm64_pass.c @@ -500,24 +500,24 @@ SETMARK(d_cmp64); SETMARK(d_tst8); LDRB_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV32w(x2, 0xff); - emit_test8(dyn, ninst, x1, x2, x3, x4, x5); + emit_test8(dyn, ninst, x1, x2, x3, x4); RET(xLR); SETMARK(d_tst16); LDRH_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV32w(x2, 0xffff); - emit_test16(dyn, ninst, x1, x2, x3, x4, x5); + emit_test16(dyn, ninst, x1, x2, x3, x4); RET(xLR); SETMARK(d_tst32); LDRw_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV32w(x2, 0xffffffff); rex.w = 0; - emit_test32(dyn, ninst, rex, x1, x2, x3, x4, x5); + emit_test32(dyn, ninst, rex, x1, x2, x3, x4); RET(xLR); SETMARK(d_tst64); LDRx_U12(x1, xEmu, offsetof(x64emu_t, res)); MOV64x(x2, 0xffffffffffffffffULL); rex.w = 1; - emit_test32(dyn, ninst, rex, x1, x2, x3, x4, x5); + emit_test32(dyn, ninst, rex, x1, x2, x3, x4); rex.w = 0; RET(xLR); // for ADC & SBB, the emit_adcX cannot be used because the CF state is not saved @@ -884,30 +884,33 @@ SETMARK(d_ror64); SETMARK(d_shrd16); LDRH_U12(x1, xEmu, offsetof(x64emu_t, res)); LDRH_U12(x2, xEmu, offsetof(x64emu_t, op1)); - LDRH_U12(x3, xEmu, offsetof(x64emu_t, op2)); - CBNZw(x3, 4+4); + LDRw_U12(x3, xEmu, offsetof(x64emu_t, op2)); + ANDw_mask(x4, x3, 0, 4); // count = op2 & 0x1f + CBNZw(x4, 4+4); RET(xLR); + LSRw(x5, x3, 16); // fill = op2 >> 16 if(BOX64ENV(cputype)) { - LSRw(x4, x1, 14); - EORw_REG_LSR(x4, x4, x4, 1); - BFIw(xFlags, x4, F_OF, 1); + LSRw(x3, x1, 14); + EORw_REG_LSR(x3, x3, x3, 1); + BFIw(xFlags, x3, F_OF, 1); ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + SUBw_U12(x3, x4, 1); + LSRw_REG(x3, x2, x3); + CMPSw_U12(x4, 16); + CSELw(x3, xZR, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); } else { - ANDw_mask(x4, x3, 0, 3); // mask = 0x0f - SUBw_U12(x4, x4, 16); - NEGw_REG(x4, x4); - LSRw_REG(x4, x1, x4); - EORw_REG_LSR(x4, x4, x2, 15); - BFIw(xFlags, x4, F_OF, 1); + EORw_REG_LSR(x3, x5, x2, 15); + BFIw(xFlags, x3, F_OF, 1); BFCw(xFlags, F_AF, 1); + CMPSw_U12(x4, 16); + SUBw_U12(x3, x4, 1); + LSRw_REG(x3, x2, x3); // dest >> (count-1) + SUBw_U12(x4, x4, 17); + LSRw_REG(x5, x5, x4); // fill >> (count-17) + CSELw(x3, x5, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); } - SUBw_U12(x4, x3, 1); - LSRw_REG(x4, x2, x4); - if(BOX64ENV(cputype)) { - CMPSw_U12(x3, 15); - CSELw(x4, x4, xZR, cGT); - } - BFIw(xFlags, x4, F_CF, 1); LSRw(x4, x1, 15); BFIw(xFlags, x4, F_SF, 1); TSTw_mask(x1, 0, 15); @@ -976,24 +979,37 @@ SETMARK(d_shrd64); SETMARK(d_shld16); LDRH_U12(x1, xEmu, offsetof(x64emu_t, res)); LDRH_U12(x2, xEmu, offsetof(x64emu_t, op1)); - LDRH_U12(x3, xEmu, offsetof(x64emu_t, op2)); - CBNZw(x3, 4+4); + LDRw_U12(x3, xEmu, offsetof(x64emu_t, op2)); + ANDw_mask(x4, x3, 0, 4); // count = op2 & 0x1f + CBNZw(x4, 4+4); RET(xLR); - SUBw_U12(x4, x3, 16); - NEGw_REG(x4, x4); - LSRw_REG(x4, x2, x4); - BFIw(xFlags, x4, F_CF, 1); + LSRw(x5, x3, 16); // fill = op2 >> 16 if(BOX64ENV(cputype)) { - EORw_REG_LSR(x4, xFlags, x1, 15); - CMPSw_U12(x3, 15); - CSELw(x4, x4, xFlags, cGT); - BFIw(xFlags, x4, F_OF, 1); + MOV32w(x3, 16); + SUBw_REG(x3, x3, x4); + LSRw_REG(x3, x2, x3); // dest >> (16-count) + CMPSw_U12(x4, 16); + CSELw(x3, xZR, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); + EORw_REG_LSR(x3, xFlags, x1, 15); + CMPSw_U12(x4, 15); + CSELw(x3, xFlags, x3, cGT); + BFIw(xFlags, x3, F_OF, 1); ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 } else { - LSRw(x4, x2, 14); - EORw_REG_LSR(x4, x4, x4, 1); - BFIw(xFlags, x4, F_OF, 1); + LSRw(x3, x2, 14); + EORw_REG_LSR(x3, x3, x3, 1); + BFIw(xFlags, x3, F_OF, 1); BFCw(xFlags, F_AF, 1); + CMPSw_U12(x4, 16); + MOV32w(x3, 16); + SUBw_REG(x3, x3, x4); + LSRw_REG(x3, x2, x3); // dest >> (16-count) + MOV32w(x2, 32); + SUBw_REG(x2, x2, x4); + LSRw_REG(x5, x5, x2); // fill >> (32-count) + CSELw(x3, x5, x3, cGT); + BFIw(xFlags, x3, F_CF, 1); } LSRw(x4, x1, 15); BFIw(xFlags, x4, F_SF, 1); diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index d81e7f352..b1d1f0c32 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -111,6 +111,8 @@ dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock) return db; } +static void QueueZombieDynablock(dynablock_t* db); + static void RetireOrphanDynablocks(void) { for (int i = 0; i < my_context->db_orphan_count; ) { @@ -119,8 +121,11 @@ static void RetireOrphanDynablocks(void) ++i; continue; } - if (db) FreeDynarecMap((uintptr_t)db->actual_block); my_context->db_orphan[i] = my_context->db_orphan[--my_context->db_orphan_count]; + // released by its last user: requeue it instead of freeing right away, a thread + // may still be running the last instructions of the block (and the enter/leave + // pair is not atomic with the code around it) + if (db) QueueZombieDynablock(db); } } @@ -139,9 +144,8 @@ static void QueueOrphanDynablock(dynablock_t* db) my_context->db_orphan[my_context->db_orphan_count++] = db; } -static void DeferFreeDynablockMap(dynablock_t* db) +static void QueueZombieDynablock(dynablock_t* db) { - if (my_context->db_orphan_count) RetireOrphanDynablocks(); // enq for a deferred free so any threads still running in this block has a better chance to finish. if (my_context->db_zombie_count == DB_ZOMBIE_SIZE) { // Queue full: free the oldest queued block that no running dynarec chain holds (in_used), compact the queue. @@ -186,6 +190,12 @@ static void DeferFreeDynablockMap(dynablock_t* db) } } +static void DeferFreeDynablockMap(dynablock_t* db) +{ + if (my_context->db_orphan_count) RetireOrphanDynablocks(); + QueueZombieDynablock(db); +} + void DeferFreeDynablockClearRange(void* addr, size_t sz) { int head = my_context->db_zombie_head; @@ -325,8 +335,10 @@ int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size) void dynablock_leave_runtime(dynablock_t* db) { if(!db) return; - if(BOX64ENV(dynarec_callret) < 2) return; +#ifdef HAVE_IN_USED + if(BOX64ENV(dynarec_callret) < 3) return; __atomic_fetch_sub(&db->in_used, 1, __ATOMIC_ACQ_REL); +#endif } dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits) @@ -373,12 +385,15 @@ dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits) return NULL if block is not found / cannot be created. Don't create if create==0 */ -dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new) +dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new, dynablock_t* block) { const uint32_t req_prot = (box64_pagesize==4096)?(PROT_EXEC|PROT_READ):PROT_READ; if(BOX64ENV(nodynarec_delay) && (addr>=BOX64ENV(nodynarec_start)) && (addrto_delete) { // just delete the block then, so we can create a new one right away FreeDynablock(block, 1, 1); @@ -488,9 +503,26 @@ void FlushZombieDynablocks(void) dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) { int is_inhotpage = isInHotPage(addr); + dynablock_t* db = NULL; + if(!is_inhotpage && !BOX64ENV(dynarec_dirty)) { + db = getDB(addr); + if(db && db->x64_size) { + uintptr_t dbstart = (uintptr_t)db->x64_addr; + uintptr_t dbend = dbstart + db->x64_size; + for(uintptr_t page = (dbstart&~(X86_PAGE_SIZE-1)); page < dbend; page += X86_PAGE_SIZE) { + if(page == (addr&~(X86_PAGE_SIZE-1))) continue; // skip the first page + if(checkInHotPage(page)) { + is_inhotpage = 1; + break; + } + } + } + if(!db) + db = SEARCHED_NO_DYNABLOCK; + } if(is_inhotpage && !BOX64ENV(dynarec_dirty)) return NULL; - dynablock_t *db = internalDBGetBlock(emu, addr, create, 1, is32bits, 1); + db = internalDBGetBlock(emu, addr, create, 1, is32bits, 1, db); if(db && db->done && db->block && getNeedTest(addr)) { //if (db->always_test) SchedYield(); // just calm down... uint32_t hash = X31_hash_code((void*)db->x64_readaddr, db->x64_size); @@ -505,7 +537,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits) dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X, gone:%d, autocrc:%d, to_delete:%d) for %p\n", db, db->x64_addr, db->x64_addr + db->x64_size, db->hash, db->gone, db->autocrc, db->to_delete, (void*)addr); dynablock_t* old = InvalidDynablock(db, 0); FreeInvalidDynablock(old, 0); - db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0); + db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0, SEARCHED_NO_DYNABLOCK); } else { if(is_inhotpage) { db->always_test = 2; diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c index 8bdbbb164..b5370ce56 100644 --- a/src/dynarec/dynarec.c +++ b/src/dynarec/dynarec.c @@ -103,12 +103,14 @@ void* LinkNextInvalid(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3) int is32bits = (R_CS == 0x23); dynablock_t* db = getDB(addr); if(db) { + // the caller entered this block before running the check that failed here + dynablock_leave_runtime(db); mutex_lock(&my_context->mutex_dyndump); db->done = 0; dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X, gone:%d, autocrc:%d, to_delete:%d) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, db->hash, db->gone, db->autocrc, db->to_delete, (void*)addr); dynablock_t* old = InvalidDynablock(db, 0); FreeInvalidDynablock(old, 0); - db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0); + db = internalDBGetBlock(emu, addr, 1, 0, is32bits, 0, SEARCHED_NO_DYNABLOCK); mutex_unlock(&my_context->mutex_dyndump); if(db && db->done && db->block && (uintptr_t)db->x64_addr == addr) return db->block; diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index 30037b8f0..30a27944d 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -8,6 +8,8 @@ #define dynarec_native_t dynarec_arm_t #define extcache_native_t neoncache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); @@ -46,14 +48,15 @@ extern void arm64_next_invalid(); #define ARCH_NOP 0b11010101000000110010000000011111 #define ARCH_UDF 0xcafe #define JMPNEXT_SIZE (4*sizeof(void*)) +#define PRINT_OPCODE(C, A) arm64_print(C, A) #elif defined(LA64) -#define HAVE_LEAFCALL - #define instruction_native_t instruction_la64_t #define dynarec_native_t dynarec_la64_t #define extcache_native_t lsxcache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); @@ -89,6 +92,7 @@ extern void la64_crc_autocrc(); // same as la64_crc, but not using regular ABI #define ADDITIONNAL_CHECKS() #define ARCH_CRC_INLINE extern void la64_next_invalid(); +#define PRINT_OPCODE(C, A) la64_print(C, A) #elif defined(RV64) @@ -96,6 +100,8 @@ extern void la64_next_invalid(); #define dynarec_native_t dynarec_rv64_t #define extcache_native_t extcache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); \ int sewNeedsTransform(dynarec_rv64_t* dyn, int ninst); @@ -114,15 +120,23 @@ extern void la64_next_invalid(); #define RAZ_SPECIFIC(A, N) #define UPDATE_SPECIFICS(A) #define PREUPDATE_SPECIFICS(A) updateNativeFlags(A) -#define POSTUPDATE_SPECIFICS(A) +#define POSTUPDATE_SPECIFICS(A) updatePreloads(A) #define ARCH_SIZE(A) get_size_arch(A) #define ARCH_FILL(A, B, C) populate_arch(A, B, C) -#define ARCH_ADJUST(A, B, C, D) {} +#define ARCH_ADJUST(A, B, C, D) adjust_arch(A, B, C, D) #define STOP_NATIVE_FLAGS(A, B) {} #define ARCH_UNALIGNED(A, B) arch_unaligned(A, B) #define ARCH_HOST_CALL(A, B, C) 0 +extern uint32_t rv64_crc(void* p, uint32_t len); +extern uint32_t rv64_crc_zbc(void* p, uint32_t len); +extern void rv64_crc_autocrc(); +extern void rv64_crc_autocrc_zbc(); +#define ARCH_CRC(A, B) return cpuext.zbc ? rv64_crc_zbc(A, B) : rv64_crc(A, B) +#define ARCH_CRC_INLINE +extern void rv64_next_invalid(); + #define ARCH_NOP 0b0010011 #define ARCH_UDF 0xc0001073 @@ -130,6 +144,7 @@ extern void la64_next_invalid(); #define ADDITIONNAL_CHECKS() extern void* create_updateflags(); #define ARCH_UPDATEFLAGS() create_updateflags() +#define PRINT_OPCODE(C, A) rv64_print(C, A) #elif defined(PPC64LE) @@ -168,6 +183,7 @@ extern void* create_updateflags(); // so the jmpnext area needs 5 void* slots (40 bytes) instead of the default 4 (32 bytes). #define JMPNEXT_SIZE (5*sizeof(void*)) #define ADDITIONNAL_CHECKS() +#define PRINT_OPCODE(C, A) ppc64le_print(C, A) #else #error Unsupported platform diff --git a/src/dynarec/dynarec_helper.h b/src/dynarec/dynarec_helper.h index 192b188e5..662733385 100644 --- a/src/dynarec/dynarec_helper.h +++ b/src/dynarec/dynarec_helper.h @@ -38,17 +38,19 @@ #define STRONGMEM_SEQ_WRITE 3 // The level of a barrier at every third memory store will be put #define STRONGMEM_QEMU 4 // The level of a mimic to QEMU's strong memory model -#define STRONGMEM_LEVEL() ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)) +#define STRONGMEM_LEVEL() (dyn->insts[ninst].x64.strongmem) #if STEP == 1 -#define SMWRITE() \ - do { \ - /* Mark that current sequence writes to guest memory. */ \ - /* This will be used in SMEND for last_write. */ \ - dyn->smwrite = 1; \ - /* Mark that current opcode writes to guest memory. */ \ - dyn->insts[ninst].will_write = 1; \ +#define SMWRITE() \ + do { \ + if(STRONGMEM_LEVEL()) { \ + /* Mark that current sequence writes to guest memory. */\ + /* This will be used in SMEND for last_write. */ \ + dyn->smwrite = 1; \ + /* Mark that current opcode writes to guest memory. */ \ + dyn->insts[ninst].will_write = 1; \ + } \ } while (0) #define SMWRITELOCK(lock) \ @@ -108,12 +110,12 @@ if (STRONGMEM_LEVEL() >= STRONGMEM_SEQ_WRITE) { \ if (++dyn->smwrite >= 3 /* Every third memory write */ \ || STRONGMEM_LEVEL() >= STRONGMEM_QEMU) { \ - DMB_ISH(); \ + DMB_TSO(); \ dyn->smwrite = 1; \ } \ } else { \ /* Mark that current sequence writes to guest memory. */ \ - dyn->smwrite = 1; \ + if(STRONGMEM_LEVEL()) dyn->smwrite = 1; \ } \ } \ } while (0) @@ -161,14 +163,14 @@ if (BOX64ENV(dynarec_weakbarrier)) \ DMB_ISHLD(); \ else \ - DMB_ISH(); \ + DMB_TSO(); \ } else if (STRONGMEM_LEVEL() >= STRONGMEM_LAST_WRITE && BOX64ENV(dynarec_weakbarrier) != 2 \ && dyn->insts[ninst].last_write) { \ /* Last write, put a barrier */ \ if (BOX64ENV(dynarec_weakbarrier)) \ DMB_ISHST(); \ else \ - DMB_ISH(); \ + DMB_TSO(); \ } \ } while (0) @@ -198,7 +200,7 @@ if (BOX64ENV(dynarec_weakbarrier)) \ DMB_ISHST(); \ else \ - DMB_ISH(); \ + DMB_TSO(); \ } \ } \ dyn->smwrite = 0; \ @@ -234,4 +236,8 @@ int is_addr_autosmc(uintptr_t addr); #error Unsupported architecture #endif +#ifndef DMB_TSO +#define DMB_TSO() DMB_ISH() +#endif + #endif //__DYNAREC_HELPER__H_ diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index f78489cb1..7106c7e0f 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -416,347 +416,6 @@ uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); -#ifdef HAVE_LEAFCALL -#define LEAFCALL_MAX_INSTS 128 -#define LEAFCALL_MAX_BYTES 4096 -#define LEAFCALL_MAX_EMBEDDEDS 32 -#define LEAFCALL_MAX_TOTAL_INSTS 512 - -typedef struct leafcall_peek_s { - dynarec_native_t dyn; - instruction_native_t insts[LEAFCALL_MAX_INSTS + 2]; - int jmps[LEAFCALL_MAX_INSTS + 2]; - uintptr_t next[LEAFCALL_MAX_INSTS + 2]; -} leafcall_peek_t; - -typedef struct leafcall_analysis_s { - uintptr_t work[LEAFCALL_MAX_INSTS]; - uintptr_t decoded[LEAFCALL_MAX_INSTS]; - uint8_t decoded_len[LEAFCALL_MAX_INSTS]; - instruction_native_t* decoded_inst; - uintptr_t body_start; - uintptr_t body_end; - int work_size; - int decoded_size; - int saw_ret; - int reads_rsp; - int implicit_rsp; - int failed; -} leafcall_analysis_t; - -typedef struct leaf_embedded_s { - dynarec_native_t dyn; -} leaf_embedded_t; - -static leaf_embedded_t static_leaf_embeddeds[LEAFCALL_MAX_EMBEDDEDS]; -static instruction_native_t static_leafinsts[LEAFCALL_MAX_TOTAL_INSTS + LEAFCALL_MAX_EMBEDDEDS]; -static int static_leafjmps[LEAFCALL_MAX_TOTAL_INSTS]; -static int static_leafpreds[LEAFCALL_MAX_TOTAL_INSTS * 2]; -static instsize_t static_leaf_instsize[LEAFCALL_INSTSIZE_SCRATCH]; -static int static_leaf_embedded_count; -static int static_leafinst_count; -static int static_leafdecoded_count; -static int static_leafpred_count; - -static int leafcall_readable(uintptr_t addr, uintptr_t size) -{ - if (!size) - return 1; - uintptr_t end = addr + size - 1; - if (end < addr) - return 0; - uintptr_t cur = addr; - while (1) { - uint32_t prot = getProtection(cur); - if ((prot & (PROT_READ | PROT_EXEC)) != (PROT_READ | PROT_EXEC)) - return 0; - uintptr_t page_end = (cur & ~(box64_pagesize - 1)) + box64_pagesize - 1; - if (end <= page_end) - return 1; - cur = page_end + 1; - } -} - -static int leafcall_seen(const leafcall_analysis_t* scan, uintptr_t addr) -{ - for (int i = 0; i < scan->decoded_size; ++i) - if (scan->decoded[i] == addr) - return 1; - return 0; -} - -static int leafcall_queue_jump(leafcall_analysis_t* scan, uintptr_t addr, uintptr_t continuation) -{ - if (!addr || addr == continuation) - return 0; - if (addr < scan->body_start || addr >= scan->body_end) - return 0; - if (leafcall_seen(scan, addr)) - return 1; - for (int i = 0; i < scan->work_size; ++i) - if (scan->work[i] == addr) - return 1; - if (scan->work_size >= LEAFCALL_MAX_INSTS) - return 0; - scan->work[scan->work_size++] = addr; - return 1; -} - -static int leafcall_check_segment(leafcall_analysis_t* scan, uintptr_t entry, uintptr_t continuation, int is32bits) -{ - if (!leafcall_readable(entry, 1) || leafcall_seen(scan, entry)) - return leafcall_seen(scan, entry); - - leafcall_peek_t peek; - memset(&peek, 0, sizeof(peek)); - dynarec_native_t* dyn = &peek.dyn; - dyn->start = entry; - dyn->end = entry + LEAFCALL_MAX_BYTES; - if (dyn->end < entry) - return 0; - uintptr_t mapped = SizeFileMapped(entry); - if (mapped && mapped < LEAFCALL_MAX_BYTES) - dyn->end = entry + mapped; - dyn->cap = LEAFCALL_MAX_INSTS + 2; - dyn->insts = peek.insts; - dyn->jmp_cap = LEAFCALL_MAX_INSTS + 2; - dyn->jmps = peek.jmps; - dyn->next_cap = LEAFCALL_MAX_INSTS + 2; - dyn->next = peek.next; - dyn->env = GetCurEnvByAddr(entry); - dyn->is_file_mapped = IsAddrElfOrFileMapped(entry); - dyn->peeking_flags = 1; - - uintptr_t end = native_pass0(dyn, entry, 0, is32bits, LEAFCALL_MAX_INSTS); - if (dyn->size <= 0 || dyn->size > LEAFCALL_MAX_INSTS || end < entry) - return 0; - - for (int i = 0; i < dyn->size; ++i) { - instruction_x64_t* inst = &dyn->insts[i].x64; - uintptr_t ip = inst->addr; - uintptr_t next = (i + 1 < dyn->size) ? dyn->insts[i + 1].x64.addr : end; - if (ip == continuation || ip < scan->body_start || next > scan->body_end) - return 0; - if (leafcall_seen(scan, ip)) - continue; - if (scan->decoded_size >= LEAFCALL_MAX_INSTS) - return 0; - scan->decoded[scan->decoded_size] = ip; - scan->decoded_len[scan->decoded_size] = next - ip; - if (scan->decoded_inst) { - scan->decoded_inst[scan->decoded_size] = dyn->insts[i]; - scan->decoded_inst[scan->decoded_size].pred = NULL; - scan->decoded_inst[scan->decoded_size].pred_sz = 0; - } - ++scan->decoded_size; - - if (dyn->insts[i].host_call) - return 0; - - if (inst->leaf_kind == LEAF_KIND_CALL) - return 0; - - int implicit_rsp = (inst->leaf_rsp & LEAF_RSP_PUSHPOP) ? 1 : 0; - if (implicit_rsp) scan->implicit_rsp = 1; - - if (inst->leaf_kind == LEAF_KIND_RET) { - scan->saw_ret = 1; - continue; - } - - uint16_t sp_bits = (dyn->insts[i].up32_read | dyn->insts[i].up32_write64 | dyn->insts[i].up32_write32 | dyn->insts[i].up32_zero) & (1u << _SP); - if ((inst->leaf_rsp & LEAF_RSP_REF) || (!implicit_rsp && sp_bits)) - scan->reads_rsp = 1; - - if (!inst->has_next) { - if (!inst->jmp || inst->jmp_cond) - return 0; - if (!leafcall_queue_jump(scan, inst->jmp, continuation)) - return 0; - continue; - } - if (inst->jmp) { - if (!inst->jmp_cond || !leafcall_queue_jump(scan, inst->jmp, continuation)) - return 0; - } - } - return 1; -} - -static int leafcall_analyze_leaf(leafcall_analysis_t* scan, uintptr_t target, uintptr_t continuation, int is32bits, instruction_native_t* decoded_inst) -{ - memset(scan, 0, sizeof(*scan)); - scan->decoded_inst = decoded_inst; - scan->body_start = target; - scan->body_end = target + LEAFCALL_MAX_BYTES; - if (scan->body_end < target) - return 0; - uintptr_t mapped = SizeFileMapped(target); - if (mapped && mapped < LEAFCALL_MAX_BYTES) - scan->body_end = target + mapped; - scan->work[scan->work_size++] = target; - while (scan->work_size && !scan->failed) { - uintptr_t entry = scan->work[--scan->work_size]; - if (!leafcall_check_segment(scan, entry, continuation, is32bits)) - scan->failed = 1; - } - if (scan->failed || !scan->saw_ret || !scan->decoded_size) - return 0; - - for (int i = 1; i < scan->decoded_size; ++i) { - uintptr_t addr = scan->decoded[i]; - uint8_t len = scan->decoded_len[i]; - instruction_native_t inst; - if (decoded_inst) - inst = decoded_inst[i]; - int j = i; - while (j && scan->decoded[j - 1] > addr) { - scan->decoded[j] = scan->decoded[j - 1]; - scan->decoded_len[j] = scan->decoded_len[j - 1]; - if (decoded_inst) - decoded_inst[j] = decoded_inst[j - 1]; - --j; - } - scan->decoded[j] = addr; - scan->decoded_len[j] = len; - if (decoded_inst) - decoded_inst[j] = inst; - } - if (scan->decoded[0] != target) - return 0; - for (int i = 1; i < scan->decoded_size; ++i) - if (scan->decoded[i] < scan->decoded[i - 1] + scan->decoded_len[i - 1]) - return 0; - return 1; -} - -static int leaf_embedded_find(const instruction_native_t* insts, int size, uintptr_t addr) -{ - int low = 0; - int high = size - 1; - while (low <= high) { - int mid = (low + high) / 2; - if (insts[mid].x64.addr == addr) - return mid; - if (insts[mid].x64.addr < addr) - low = mid + 1; - else - high = mid - 1; - } - return -1; -} - -static int leaf_embedded_build(uintptr_t target, uintptr_t continuation, int is32bits, uint8_t* embedded_id) -{ - instruction_native_t decoded[LEAFCALL_MAX_INSTS + 2]; - leafcall_analysis_t scan; - if (!embedded_id || static_leaf_embedded_count >= LEAFCALL_MAX_EMBEDDEDS || BOX64ENV(dynarec_test) || BOX64ENV(dynarec_trace)) - return 0; -#ifdef HAVE_ALTJUMP - if (getAlternateJump((void*)target, is32bits)) - return 0; -#endif - if (!leafcall_analyze_leaf(&scan, target, continuation, is32bits, decoded)) - return 0; - if (static_leafdecoded_count + scan.decoded_size > LEAFCALL_MAX_TOTAL_INSTS || static_leafinst_count + scan.decoded_size + 1 > (int)(sizeof(static_leafinsts) / sizeof(static_leafinsts[0]))) - return 0; - - leaf_embedded_t* embedded = &static_leaf_embeddeds[static_leaf_embedded_count]; - memset(embedded, 0, sizeof(*embedded)); - dynarec_native_t* leaf = &embedded->dyn; - leaf->insts = &static_leafinsts[static_leafinst_count]; - memcpy(leaf->insts, decoded, scan.decoded_size * sizeof(decoded[0])); - memset(&leaf->insts[scan.decoded_size], 0, sizeof(leaf->insts[scan.decoded_size])); - leaf->size = scan.decoded_size; - leaf->cap = scan.decoded_size + 1; - leaf->start = target; - leaf->end = scan.decoded[scan.decoded_size - 1] + scan.decoded_len[scan.decoded_size - 1]; - leaf->isize = leaf->end - target; - leaf->env = GetCurEnvByAddr(target); - leaf->is_file_mapped = IsAddrElfOrFileMapped(target); - leaf->peeking_flags = 2; - leaf->inline_leaf = 1; - leaf->inline_is32bits = is32bits; - leaf->inline_rsp = scan.reads_rsp ? 0 : (scan.implicit_rsp ? (is32bits ? 4 : 8) : -(is32bits ? 4 : 8)); - leaf->instsize = static_leaf_instsize; - leaf->jmps = &static_leafjmps[static_leafdecoded_count]; - leaf->jmp_cap = scan.decoded_size; - - for (int i = 0; i < leaf->size; ++i) { - instruction_native_t* inst = &leaf->insts[i]; - inst->x64.size = scan.decoded_len[i]; - inst->x64.alive = 0; - inst->x64.jmp_insts = -1; - inst->pred = NULL; - inst->pred_sz = 0; - if (inst->x64.has_next) { - if (i + 1 >= leaf->size || inst->x64.addr + inst->x64.size != leaf->insts[i + 1].x64.addr) - return 0; - } - if (inst->x64.jmp) { - int target_inst = leaf_embedded_find(leaf->insts, leaf->size, inst->x64.jmp); - if (target_inst < 0) - return 0; - inst->x64.jmp_insts = target_inst; - inst->barrier_maybe = 0; - leaf->jmps[leaf->jmp_sz++] = i; - } - int isret = (inst->x64.leaf_kind == LEAF_KIND_RET); - if (isret) - inst->x64.need_after |= X_PEND; - } - leaf->insts[leaf->size].x64.addr = leaf->end; - - sizePredecessors(leaf); - int predecessor_count = 0; - for (int i = 0; i < leaf->size; ++i) - predecessor_count += leaf->insts[i].pred_sz; - if (static_leafpred_count + predecessor_count > (int)(sizeof(static_leafpreds) / sizeof(static_leafpreds[0]))) - return 0; - leaf->predecessor = &static_leafpreds[static_leafpred_count]; - fillPredecessors(leaf); - for (int i = 0; i < leaf->size; ++i) - if (!leaf->insts[i].x64.alive) - return 0; - - PREUPDATE_SPECIFICS(leaf); - int pos = leaf->size - 1; - while (pos >= 0) - pos = updateNeed(leaf, pos, 0); - updateUpperLiveness(leaf); - updateRspMerge(leaf, is32bits); - UPDATE_SPECIFICS(leaf); - - static_leafinst_count += leaf->size + 1; - static_leafdecoded_count += leaf->size; - static_leafpred_count += predecessor_count; - *embedded_id = ++static_leaf_embedded_count; - return 1; -} - -static void leaf_embedded_reset(dynarec_native_t* dyn) -{ - static_leaf_embedded_count = 0; - static_leafinst_count = 0; - static_leafdecoded_count = 0; - static_leafpred_count = 0; - memset(static_leaf_embeddeds, 0, sizeof(static_leaf_embeddeds)); - dyn->leaf_embeddeds = static_leaf_embeddeds; -} - -void* dynarec_get_leaf_embedded(void* owner, int ninst) -{ - dynarec_native_t* dyn = owner; - if (!dyn || !dyn->leaf_embeddeds || ninst < 0 || ninst >= dyn->size) - return NULL; - int embedded_id = dyn->insts[ninst].x64.leaf_embedded; - if (embedded_id <= 0 || embedded_id > static_leaf_embedded_count) - return NULL; - leaf_embedded_t* embeddeds = dyn->leaf_embeddeds; - return &embeddeds[embedded_id - 1].dyn; -} -#endif - #define PEEK_FLAGS_INSTS 16 typedef struct peek_flags_state_s { @@ -948,9 +607,6 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, helper.next_cap = MAX_INSTS; helper.table64 = NULL; helper.env = GetCurEnvByAddr(addr); - #ifdef HAVE_LEAFCALL - leaf_embedded_reset(&helper); - #endif if(prot&PROT_NEVERCLEAN) { helper.always_test = 1; } @@ -995,6 +651,8 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, if(state==BUILD_PASS0 && helper.size>1) { --helper.size; end = helper.insts[helper.size].x64.addr; + if(interblock_flags_needed(&helper, end, is32bits)) + helper.insts[helper.size - 1].x64.need_after |= X_PEND; printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, truncating at %d(%p)\n", (void*)addr, helper.size, (void*)end); state = BUILD_PASS1; } else { @@ -1031,33 +689,6 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, state = BUILD_ABORT_EMPTY; continue; } - #ifdef HAVE_LEAFCALL - if (BOX64DRENV(dynarec_callret) >= 3) { - for (int i = 0; i < helper.size; ++i) { - instruction_x64_t* inst = &helper.insts[i].x64; - if (inst->leaf_kind != LEAF_KIND_CALL) - continue; - uintptr_t target = inst->leaf_target; - uintptr_t continuation = inst->addr + inst->size; - uint8_t embedded_id = 0; - if (!target || !inst->has_next || i + 1 >= helper.size || helper.insts[i + 1].x64.addr != continuation || !leaf_embedded_build(target, continuation, is32bits, &embedded_id)) - inst->leaf_call = 0; - else - inst->leaf_embedded = embedded_id; - } - for (int i = 0; i < helper.size; ++i) - if (helper.insts[i].x64.leaf_call) - helper.insts[i].x64.barrier = BARRIER_FLOAT; - } else { - for (int i = 0; i < helper.size; ++i) { - helper.insts[i].x64.leaf_call = 0; - helper.insts[i].x64.leaf_embedded = 0; - helper.insts[i].x64.leaf_kind = LEAF_KIND_NONE; - helper.insts[i].x64.leaf_rsp = 0; - helper.insts[i].x64.leaf_target = 0; - } - } - #endif if(!is_inhotpage && !isprotectedDB(addr, 1)) { dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr); state = BUILD_ABORT_NULL; @@ -1155,7 +786,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int pos = helper.size-1; while (pos>=0) pos = updateNeed(&helper, pos, 0); - #if defined(LA64) + #if defined(LA64) || defined(RV64) updateUpperLiveness(&helper); updateRspMerge(&helper, is32bits); #endif diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index fa8c58d56..2a6a7f301 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 3a6db2fd7..7d05b86c9 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -113,18 +113,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int dyn->forward_ninst = 0; dyn->ymm_zero = 0; dyn->is_file_mapped = IsAddrElfOrFileMapped(addr); - int dynarec_dirty = BOX64ENV(dynarec_dirty); #if STEP == 0 memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t)); #endif fpu_reset(dyn); ARCH_INIT(); int reset_n = -1; // -1 no reset; -2 reset to 0; else reset to the state of reset_n - #if defined(HAVE_LEAFCALL) - dyn->last_ip = (dyn->inline_leaf || alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of ordinary blocks unless there is a predecessor! - #else dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of block unless there is a predecessor! - #endif int stopblock = 2 + !dyn->is_file_mapped; // if block is in elf memory or file mapped memory, it can be extended with BOX64DRENV(dynarec_bigblock)==2, else it needs 3 // ok, go now INIT; @@ -132,10 +127,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int uintptr_t cur_page = ALIGN_DOWN(addr); #endif while(ok) { - #if STEP > 0 && defined(HAVE_LEAFCALL) - if (dyn->inline_leaf) - addr = dyn->insts[ninst].x64.addr; - #endif #if STEP == 0 int stop_for_guard = 0; if(cur_page != (ALIGN_DOWN(addr))) { @@ -168,19 +159,9 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int NATIVE_RESTORE_X87PC(); } ip = addr; - #ifdef ARM64 + #if defined(ARM64) || defined(LA64) || defined(RV64) if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) - doEnterBlock(dyn, 0, x1, x2, x3); - if(dyn->always_test) - checkCRC(dyn, 0); - if(dyn->insts[0].preload_xmmymm) - doPreload(dyn, 0); - ENDPREFIX; - } - #elif defined(LA64) - if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); if(dyn->always_test) checkCRC(dyn, 0); @@ -189,11 +170,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } ENDPREFIX; } - #elif defined(RV64) - if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) - doEnterBlock(dyn, 0, x1, x2, x3); - } #endif fpu_propagate_stack(dyn, ninst); if (reset_n!=-1) { @@ -237,10 +213,29 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } else if (dyn->insts[ninst].will_write) { WILLWRITE(); } - + #endif int is_opcode_volatile = /*box64_wine &&*/ VolatileRangesContains(ip) && VolatileOpcodesHas(ip); - if (is_opcode_volatile && !dyn->insts[ninst].lock && dyn->insts[ninst].will_write) - DMB_ISHST(); + #if defined(ARM64) && STEP == 1 + if(is_opcode_volatile && cpuext.lrcpc && cpuext.lrcpc2 && cpuext.uscat) dyn->insts[ninst].use_lrcpc = 1; + #endif + #if STEP > 1 + #ifdef ARM64 + if (is_opcode_volatile && dyn->insts[ninst].use_lrcpc && dyn->insts[ninst].lock) + NOLRCPC(); + #endif + if (is_opcode_volatile && !dyn->insts[ninst].lock) { + #ifdef ARM64 + if(!dyn->insts[ninst].use_lrcpc) { + #endif + if(dyn->insts[ninst].will_write) + DMB_ISHST(); + #ifdef ARM64 + } else { + SMEND(); + } + #endif + } + #endif if (BOX64DRENV(dynarec_dump) && (!BOX64ENV(dynarec_dump_range_end) || (ip >= BOX64ENV(dynarec_dump_range_start) && ip < BOX64ENV(dynarec_dump_range_end)))) { dyn->need_dump = BOX64DRENV(dynarec_dump) == 3 && STEP != 3 ? 0 : BOX64DRENV(dynarec_dump); @@ -251,7 +246,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int MESSAGE(LOG_DUMP, "TEST STEP ----\n"); extcache_native_t save; fpu_save_and_unwind(dyn, ninst, &save); - #ifdef LA64 + #if defined(LA64) || defined(RV64) UP32_READALL(); #endif fpu_reflectcache(dyn, ninst, x1, x2, x3); @@ -268,7 +263,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int #if defined (SPILL_NF_REGISTERS) if (BOX64ENV(dynarec_nativeflags)) SPILL_NF_REGISTERS; #endif - #ifdef LA64 + #if defined(LA64) || defined(RV64) UP32_READALL(); #endif fpu_reflectcache(dyn, ninst, x1, x2, x3); @@ -322,19 +317,21 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int return ip; INST_EPILOG; - #if STEP == 0 && defined(HAVE_LEAFCALL) - if (!dyn->peeking_flags && BOX64DRENV(dynarec_callret) >= 3 && dyn->insts[ninst].x64.leaf_kind == LEAF_KIND_CALL && dyn->insts[ninst].x64.leaf_target) { - dyn->insts[ninst].x64.leaf_call = 1; - } - #endif - #if STEP > 1 if (dyn->insts[ninst].lock) DMB_ISH(); - else if (is_opcode_volatile && dyn->insts[ninst].will_read) - DMB_ISHLD(); + else if (is_opcode_volatile) { + #ifdef ARM64 + if(!dyn->insts[ninst].use_lrcpc) { + #endif + if(dyn->insts[ninst].will_read) + DMB_ISHLD(); + #ifdef ARM64 + } + #endif + } #endif - #if defined(ARM64) || defined(LA64) + #if defined(ARM64) || defined(LA64) || defined(RV64) if(dyn->insts[ninst].x64.has_next && dyn->insts[ninst+1].preload_xmmymm) { doPreload(dyn, ninst+1); } @@ -359,12 +356,17 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int dyn->last_ip = 0; } } + #if defined(RV64) + if(dyn->insts[ninst].x64.has_next && dyn->insts[next].promote_ymm && !(dyn->insts[next].x64.barrier & BARRIER_FLOAT)) { + avx_promote_upper(dyn, ninst, x1, dyn->insts[next].promote_ymm); + } + #endif #endif #ifndef PROT_READ #define PROT_READ 1 #endif #if STEP == 0 - if(dynarec_dirty && ok && is_addr_autosmc(ip)) { + if(ok && is_addr_autosmc(ip)) { // this is the last opcode, because it will write in current block if not stopped ok = 0; need_epilog = 1; @@ -387,6 +389,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int addr += dyn->insts[ninst].x64.size; INST_EPILOG; } + if ((ninst + 1) < dyn->size) dyn->insts[ninst + 1].x64.barrier |= BARRIER_FLOAT; } if((dyn->insts[ninst+1].x64.barrier&BARRIER_FULL)==BARRIER_FULL) reset_n = -2; // hack to say Barrier! @@ -551,60 +554,3 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size); return addr; } - -#ifdef HAVE_LEAFCALL -void emit_inline_leaf(dynarec_native_t* parent, int parent_ninst) -{ - dynarec_native_t* leaf = dynarec_get_leaf_embedded(parent, parent_ninst); - if (!leaf) { - parent->abort = 1; - return; - } - - leaf->block = parent->block; - leaf->native_start = parent->native_start; - leaf->native_size = parent->native_size; - leaf->table64 = parent->table64; - leaf->table64size = parent->table64size; - leaf->table64cap = parent->table64cap; - leaf->tablestart = parent->tablestart; - leaf->jmp_next = parent->jmp_next; - leaf->dynablock = parent->dynablock; - leaf->callrets = parent->callrets; - leaf->callret_size = parent->callret_size; - leaf->need_dump = parent->need_dump; - leaf->need_reloc = parent->need_reloc; - leaf->relocs = parent->relocs; - leaf->reloc_size = parent->reloc_size; - leaf->inline_native_end = parent->insts[parent_ninst].mark[2]; - leaf->insts_size = 0; - leaf->abort = 0; - - size_t native_start = leaf->native_size; - native_pass(leaf, leaf->start, 0, leaf->inline_is32bits, leaf->size); - size_t native_delta = leaf->native_size - native_start; - - parent->block = leaf->block; - parent->native_size = leaf->native_size; - parent->table64size = leaf->table64size; - parent->callret_size = leaf->callret_size; - parent->reloc_size = leaf->reloc_size; - parent->abort |= leaf->abort; - - #if STEP == 1 - POSTUPDATE_SPECIFICS(leaf); - #elif STEP == 2 - parent->insts[parent_ninst].size += native_delta; - if (leaf->insts_size > LEAFCALL_INSTSIZE_SCRATCH) - parent->abort = 1; - #elif STEP == 3 - parent->insts[parent_ninst].size2 += native_delta; - for (int i = 0; i < leaf->size; ++i) { - if (!leaf->insts[i].x64.alive) - continue; - if (leaf->insts[i].size2 != leaf->insts[i].size) - parent->abort = 1; - } - #endif -} -#endif diff --git a/src/dynarec/dynarec_private.h b/src/dynarec/dynarec_private.h index e44ac0e07..86a44003c 100644 --- a/src/dynarec/dynarec_private.h +++ b/src/dynarec/dynarec_private.h @@ -36,12 +36,6 @@ #define NAT_FLAGS_FUSION 0 #define NAT_FLAGS_NOFUSION 1 -#define LEAF_KIND_NONE 0 -#define LEAF_KIND_CALL 1 -#define LEAF_KIND_RET 2 -#define LEAF_RSP_PUSHPOP 1 -#define LEAF_RSP_REF 2 - typedef struct instruction_x64_s { uintptr_t addr; //address of the instruction int32_t size; // size of the instruction @@ -50,7 +44,6 @@ typedef struct instruction_x64_s { uint8_t jmp_cond:1; // 1 of conditionnal jump uint8_t has_next:1; // does this opcode can continue to the next? uint8_t has_callret:1; // this instruction have an optimized call setup - uint8_t leaf_call:1; // direct call to a proven closed leaf body uint8_t alive:1; // this opcode gets executed (0 if dead code in that block) uint8_t self_loop:1; // this is a landing address for a self-loop (loop on itslef with no exit) uint8_t barrier; // next instruction is a jump point, so no optim allowed @@ -61,10 +54,7 @@ typedef struct instruction_x64_s { uint8_t gen_flags; // calculated uint8_t need_before;// calculated uint8_t need_after; // calculated - uint8_t leaf_embedded; - uint8_t leaf_kind; - uint8_t leaf_rsp; - uintptr_t leaf_target; + uint8_t strongmem:3; // strongmem model at the opcode } instruction_x64_t; #endif //__DYNAREC_PRIVATE_H_ diff --git a/src/dynarec/la64/dynarec_la64_00_0.c b/src/dynarec/la64/dynarec_la64_00_0.c index 4bc033367..0ca58e983 100644 --- a/src/dynarec/la64/dynarec_la64_00_0.c +++ b/src/dynarec/la64/dynarec_la64_00_0.c @@ -105,7 +105,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); break; case 0x06: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH ES"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_ES])); @@ -126,7 +125,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x07: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP ES"); SMREAD(); @@ -195,7 +193,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; case 0x0E: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH CS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_CS])); @@ -283,7 +280,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); break; case 0x16: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH SS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_SS])); @@ -304,7 +300,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x17: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP SS"); SMREAD(); @@ -380,7 +375,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); break; case 0x1E: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH DS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_DS])); @@ -401,7 +395,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x1F: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP DS"); SMREAD(); diff --git a/src/dynarec/la64/dynarec_la64_00_1.c b/src/dynarec/la64/dynarec_la64_00_1.c index 699718082..d1a562c3b 100644 --- a/src/dynarec/la64/dynarec_la64_00_1.c +++ b/src/dynarec/la64/dynarec_la64_00_1.c @@ -93,7 +93,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x56: case 0x57: INST_NAME("PUSH reg"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SCRATCH_USAGE(0); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); MARKREGsz(gd); @@ -110,8 +109,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x5E: case 0x5F: INST_NAME("POP reg"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); - if (opcode == 0x5C) MARK_LEAF_RSP(LEAF_RSP_REF); SCRATCH_USAGE(0); SMREAD(); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); @@ -122,7 +119,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x60: if (rex.is32bits) { INST_NAME("PUSHAD"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); MV(x1, xRSP); PUSH1_32(xRAX); PUSH1_32(xRCX); @@ -150,7 +146,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x61: if (rex.is32bits) { INST_NAME("POPAD"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SMREAD(); POP1_32(xRDI); POP1_32(xRSI); @@ -250,7 +245,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x68: INST_NAME("PUSH Id"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); i64 = F32S; if (PK(0) == 0xC3) { @@ -320,7 +314,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x6A: INST_NAME("PUSH Ib"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); i64 = F8S; if (!i64) { diff --git a/src/dynarec/la64/dynarec_la64_00_2.c b/src/dynarec/la64/dynarec_la64_00_2.c index bb1f1df6b..553470554 100644 --- a/src/dynarec/la64/dynarec_la64_00_2.c +++ b/src/dynarec/la64/dynarec_la64_00_2.c @@ -605,7 +605,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int switch ((nextop >> 3) & 7) { case 0: INST_NAME("POP Ed"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SMREAD(); MARKREGsdz(xRSP); if (MODREG) { @@ -679,7 +678,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x9A: - MARK_LEAF_CALL(); if (rex.is32bits) { DEFAULT; } else { @@ -716,7 +714,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x9C: INST_NAME("PUSHF"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); READFLAGS(X_ALL); RESTORE_EFLAGS(x1); if (!rex.is32bits) UP32_READ(xRSP); @@ -724,7 +721,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x9D: INST_NAME("POPF"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); if (!rex.is32bits) UP32_READ(xRSP); POP1z(xFlags); diff --git a/src/dynarec/la64/dynarec_la64_00_3.c b/src/dynarec/la64/dynarec_la64_00_3.c index 6e1bc44d3..f5c4baf17 100644 --- a/src/dynarec/la64/dynarec_la64_00_3.c +++ b/src/dynarec/la64/dynarec_la64_00_3.c @@ -346,64 +346,32 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC2: INST_NAME("RETN"); - MARK_LEAF_RET(); if (BOX64DRENV(dynarec_safeflags)) { READFLAGS(X_PEND); // lets play safe here too } BARRIER(BARRIER_FLOAT); u16 = F16; if (!rex.is32bits) UP32_READ(xRSP); - if (dyn->inline_leaf) { - if (dyn->inline_rsp >= 0) - ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8); - } else { - POP1z(xRIP); - } + POP1z(xRIP); if (u16 < 2048) ADDIz(xRSP, xRSP, u16); else { MOV32w(x1, u16); ADDz(xRSP, xRSP, x1); } - if (dyn->inline_leaf) { - SMEND(); - CHECK_DFNONE(0); - if (ninst + 1 < dyn->size) { - j64 = dyn->inline_native_end - dyn->native_size; - B(j64); - } - CLEARIP(); - } else { - ret_to_next(dyn, ip, ninst, rex); - } + ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; case 0xC3: INST_NAME("RET"); - MARK_LEAF_RET(); if (BOX64DRENV(dynarec_safeflags)) { READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } BARRIER(BARRIER_FLOAT); if (!rex.is32bits) UP32_READ(xRSP); - if (dyn->inline_leaf) { - if (dyn->inline_rsp >= 0) - ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8); - } else { - POP1z(xRIP); - } - if (dyn->inline_leaf) { - SMEND(); - CHECK_DFNONE(0); - if (ninst + 1 < dyn->size) { - j64 = dyn->inline_native_end - dyn->native_size; - B(j64); - } - CLEARIP(); - } else { - ret_to_next(dyn, ip, ninst, rex); - } + POP1z(xRIP); + ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -517,7 +485,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC8: INST_NAME("ENTER Iw,Ib"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); u16 = F16; u8 = (F8) & 0x1f; if (!rex.is32bits) { @@ -546,7 +513,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC9: INST_NAME("LEAVE"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); MARKREGsz(xRBP); MVz(xRSP, xRBP); POP1z(xRBP); @@ -1323,7 +1289,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xE8: INST_NAME("CALL Id"); i32 = (rex.is32bits && rex.is66) ? F16S : F32S; - MARK_LEAF_CALL(); if (addr + i32 == 0) { #if STEP == 3 printf_log(LOG_INFO, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr - 1)); @@ -1431,32 +1396,12 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } // regular call BARRIER(BARRIER_FLOAT); - int leaf_call = dyn->insts[ninst].x64.leaf_call && - dyn->insts[ninst].x64.leaf_embedded && - BOX64DRENV(dynarec_callret) >= 3; - dynarec_la64_t* leaf_embedded = leaf_call ? dynarec_get_leaf_embedded(dyn, ninst) : NULL; - if (!leaf_embedded) - leaf_call = 0; - uintptr_t leaf_target = rex.is32bits ? (uint32_t)(addr + i32) : addr + i32; - MARK_LEAF_CALL_TARGET(leaf_target); - if (!leaf_call || !leaf_embedded->inline_rsp) { - if (dyn->need_reloc) { - TABLE64(x2, addr); - } else { - MOV64x(x2, addr); - } - PUSH1z(x2); - } else if (leaf_embedded->inline_rsp > 0) { - ADDIz(xRSP, xRSP, -leaf_embedded->inline_rsp); - } - if (leaf_call) { - SET_HASCALLRET(); - MESSAGE(LOG_DUMP, "Embedded leaf call:\n"); - emit_inline_leaf(dyn, ninst); - MARK3; - CLEARIP(); - break; + if (dyn->need_reloc) { + TABLE64(x2, addr); + } else { + MOV64x(x2, addr); } + PUSH1z(x2); int can_continue = (addr < (dyn->start + dyn->isize)); if (BOX64DRENV(dynarec_callret)) { SET_HASCALLRET(); @@ -1475,7 +1420,7 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int *ok = 0; *need_epilog = 0; } - j64 = leaf_target; + j64 = rex.is32bits ? (uint32_t)(addr + i32) : addr + i32; j64 = (uintptr_t)getAlternate((void*)j64); jump_to_next(dyn, j64, 0, ninst, rex.is32bits); CALLRET_RET(can_continue); @@ -1490,6 +1435,8 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int MOV64x(x4, j64); } LD_D(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -1976,6 +1923,7 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int MARKREGd(xRAX); MARKREGd(xRDX); SET_DFNONE(); + CHECK_DFNONE(1); GETSED(0); if (BOX64ENV(dynarec_div0)) { BNE_MARK3(ed, xZR); @@ -2147,7 +2095,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 2: INST_NAME("CALL Ed"); - MARK_LEAF_CALL(); PASS2IF ((BOX64DRENV(dynarec_safeflags) > 1) || ((ninst && dyn->insts[ninst - 1].x64.set_flags) || ((ninst > 1) && dyn->insts[ninst - 2].x64.set_flags)), 1) { READFLAGS(X_PEND); // that's suspicious } else { @@ -2195,12 +2142,13 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD_D(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); break; case 3: // CALL FAR Ed - MARK_LEAF_CALL(); if (MODREG) { DEFAULT; } else { @@ -2261,6 +2209,8 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD_D(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -2295,7 +2245,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 6: // Push Ed INST_NAME("PUSH Ed"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); GETEDz(0); PUSH1z(ed); diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 617306182..c10c0aa32 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -300,12 +300,12 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0x17: nextop = F8; - INST_NAME("MOVHPS Ex,Gx"); - GETGX(v0, 0); if (MODREG) { - v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1); - VEXTRINS_D(v1, v0, 0x01); + INST_NAME("Illegal 0F 17"); + UDF(); } else { + INST_NAME("MOVHPS Ex,Gx"); + GETGX(v0, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); VSTELM_D(v0, ed, 0, 1); SMWRITE2(); @@ -1669,13 +1669,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni #undef GO case 0xA0: INST_NAME("PUSH FS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_FS])); PUSH1z(x2); break; case 0xA1: INST_NAME("POP FS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); POP1z(x2); ST_H(x2, xEmu, offsetof(x64emu_t, segs[_FS])); CBZ_NEXT(x2); @@ -1754,13 +1752,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xA8: INST_NAME("PUSH GS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_GS])); PUSH1z(x2); break; case 0xA9: INST_NAME("POP GS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); POP1z(x2); ST_H(x2, xEmu, offsetof(x64emu_t, segs[_GS])); CBZ_NEXT(x2); diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index f0dfa8d65..aabeba92c 100644 --- a/src/dynarec/la64/dynarec_la64_660f.c +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -804,8 +804,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xDB: INST_NAME("AESIMC Gx, Ex"); // AES-NI nextop = F8; - GETEX_AES(q1, 0, 0); - GETGX_empty(q0); + if (MODREG) { + GETEX_AES(q1, 0, 0); + GETGX_empty(q0); + } else { + GETGX_empty(q0); + GETEX_AES(q1, 0, 0); + } if (q0 != q1) { VOR_V(q0, q1, q1); } @@ -815,8 +820,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AESENC Gx, Ex"); // AES-NI nextop = F8; GETG; - GETEX_AES(q1, 0, 0); GETGX(q0, 1); + GETEX_AES(q1, 0, 0); if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) { d0 = SCRATCH; VOR_V(d0, q1, q1); @@ -843,8 +848,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AESDEC Gx, Ex"); // AES-NI nextop = F8; GETG; - GETEX_AES(q1, 0, 0); GETGX(q0, 1); + GETEX_AES(q1, 0, 0); if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) { d0 = SCRATCH; VOR_V(d0, q1, q1); @@ -857,8 +862,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AESDECLAST Gx, Ex"); // AES-NI nextop = F8; GETG; - GETEX_AES(q1, 0, 0); GETGX(q0, 1); + GETEX_AES(q1, 0, 0); if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) { d0 = SCRATCH; VOR_V(d0, q1, q1); diff --git a/src/dynarec/la64/dynarec_la64_arch.c b/src/dynarec/la64/dynarec_la64_arch.c index 29cb72c9a..44559cecc 100644 --- a/src/dynarec/la64/dynarec_la64_arch.c +++ b/src/dynarec/la64/dynarec_la64_arch.c @@ -19,21 +19,39 @@ typedef struct arch_arch_s { uint16_t unaligned : 1; uint16_t host_call : 1; // instruction performs a native call - uint16_t seq : 10; // how many instruction on the same values + uint16_t vec : 1; // vector registers of the block are cached + uint16_t seq : 9; // how many instruction on the same values uint16_t up32; // GPRs with pending 32-bit zero-up at this instruction uint16_t ymm_zero; // YMM upper halves with a deferred architectural zero int16_t rsp; // pending rsp offset at this instruction uint32_t call_window; // spill offset within the instruction + uint16_t xmm; // XMMs with their value cached in a vector register + uint16_t ymm; // YMM upper halves cached in a vector register + uint8_t x87; // x87 stack registers cached in a vector register + uint8_t mmx; // MMX registers cached in a vector register + uint32_t x87_pos; // vector register of each stack register, 3 bits each + uint16_t x87_type; // type of each cached x87 value, 2 bits each + int8_t x87delta; // pending x87 stack count at this instruction + uint8_t scalar[8]; // per scalar slot (reg 16..23): guest xmm | 0x10 if double, 0xFF if unused } arch_arch_t; typedef struct arch_build_s { uint8_t unaligned; uint8_t host_call; + uint16_t vec; uint16_t up32; uint16_t ymm_zero; int16_t rsp; uint32_t call_window; + uint16_t xmm; + uint16_t ymm; + uint8_t x87; + uint8_t mmx; + uint32_t x87_pos; + uint16_t x87_type; + int8_t x87delta; + uint8_t scalar[8]; } arch_build_t; static int arch_build(dynarec_la64_t* dyn, int ninst, arch_build_t* arch) @@ -47,7 +65,42 @@ static int arch_build(dynarec_la64_t* dyn, int ninst, arch_build_t* arch) arch->up32 = dyn->insts[ninst].up32_pending; arch->ymm_zero = dyn->insts[ninst].vector_liveness.ymm_pending; arch->rsp = dyn->insts[ninst].rsp_entry; - return arch->unaligned || arch->host_call || arch->up32 || arch->ymm_zero || arch->rsp; + arch->x87delta = dyn->insts[ninst].lsx.x87stack; + for (int i = 0; i < 16; ++i) { + if (dyn->insts[ninst].lsx.ssecache[i].v != -1) arch->xmm |= (uint16_t)(1 << i); + if (dyn->insts[ninst].lsx.avxcache[i].v != -1) arch->ymm |= (uint16_t)(1 << i); + } + for (int i = 0; i < 8; ++i) arch->scalar[i] = 0xFF; + int scalar_used = 0; + for (int i = 16; i < 24; ++i) { + int n = dyn->insts[ninst].lsx.lsxcache[i].n; + if (dyn->insts[ninst].lsx.lsxcache[i].v) { + switch (dyn->insts[ninst].lsx.lsxcache[i].t) { + case LSX_CACHE_ST_D: + case LSX_CACHE_ST_F: + case LSX_CACHE_ST_I64: + if (n < 0 || n > 7) break; + arch->x87 |= (uint8_t)(1 << n); + arch->x87_pos |= (uint32_t)(i - 16) << (n * 3); + arch->x87_type |= (uint16_t)(dyn->insts[ninst].lsx.lsxcache[i].t - + LSX_CACHE_ST_D) + << (n * 2); + break; + case LSX_CACHE_MM: + if (i == 16 + n) arch->mmx |= (uint8_t)(1 << n); + break; + case LSX_CACHE_XMM_S: + case LSX_CACHE_XMM_D: + arch->scalar[i - 16] = (uint8_t)((n & 0x0F) | ((dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_XMM_D) ? 0x10 : 0)); + scalar_used = 1; + break; + default: break; + } + } + } + arch->vec = (arch->xmm || arch->ymm || arch->x87 || arch->mmx || scalar_used); + return arch->unaligned || arch->host_call || arch->vec || arch->up32 || arch->ymm_zero || + arch->rsp || arch->x87delta; } size_t get_size_arch(dynarec_la64_t* dyn) @@ -61,7 +114,7 @@ size_t get_size_arch(dynarec_la64_t* dyn) if(!dyn->size) return 0; for(int i=0; isize; ++i) { last = arch_build(dyn, i, &build); - if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<10)-1)) && i) { + if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<9)-1)) && i) { // same sequence, increment ++seq; } else { @@ -85,6 +138,15 @@ static void build_next(arch_arch_t* arch, arch_build_t* build) arch->up32 = build->up32; arch->ymm_zero = build->ymm_zero; arch->rsp = build->rsp; + arch->vec = build->vec; + arch->xmm = build->xmm; + arch->ymm = build->ymm; + arch->x87 = build->x87; + arch->mmx = build->mmx; + arch->x87_pos = build->x87_pos; + arch->x87_type = build->x87_type; + arch->x87delta = build->x87delta; + memcpy(arch->scalar, build->scalar, sizeof(arch->scalar)); } void* populate_arch(dynarec_la64_t* dyn, void* p, size_t sz) @@ -97,7 +159,7 @@ void* populate_arch(dynarec_la64_t* dyn, void* p, size_t sz) int seq = 0; for(int i=0; isize; ++i) { arch_build(dyn, i, &build); - if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<10)-1)) && i) { + if((!memcmp(&build, &previous, sizeof(arch_build_t))) && (seq<((1<<9)-1)) && i) { // same sequence, increment seq++; arch->seq = seq; @@ -164,7 +226,6 @@ int arch_host_call(dynablock_t* db, void* native_pc, uintptr_t x64pc) void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) { - (void)p; if(!db) return; if(!db->arch_size || !db->arch) return; int ninst = getX64AddressInst(db, x64pc); @@ -183,4 +244,76 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) emu->ymm[r].u128 = 0; } if (arch->rsp && !arch->host_call) emu->regs[_SP].q[0] += arch->rsp; + if (arch->x87delta) { + emu->fpu_stack += arch->x87delta; + emu->top = (emu->top - arch->x87delta) & 7; + } + if (arch->vec && !arch->host_call) { + struct sctx_info* info = (struct sctx_info*)p->uc_mcontext.__extcontext; + uint64_t* vec = NULL; + int stride = 0; + while (info->magic && !vec) { + if (info->magic == LSX_CTX_MAGIC || info->magic == LASX_CTX_MAGIC || + info->magic == FPU_CTX_MAGIC) { + stride = (info->magic == LASX_CTX_MAGIC) + ? 4 + : ((info->magic == LSX_CTX_MAGIC) ? 2 : 1); + vec = (uint64_t*)((uintptr_t)info + sizeof(struct sctx_info)); + } else { + info = (struct sctx_info*)((uintptr_t)info + info->size); + } + } + if (vec) { + uint16_t xmm = arch->xmm; + uint16_t ymm = arch->ymm; + for (int i = 0; i < 16; ++i) { + if (!((xmm >> i) & 1) && !((ymm >> i) & 1)) continue; + if (stride == 1) { + emu->xmm[i].q[0] = vec[i]; + } else { + memcpy(&emu->xmm[i].u128, &vec[i * stride], 16); + if ((ymm >> i) & 1) { + if ((arch->ymm_zero >> i) & 1) + emu->ymm[i].u128 = 0; + else if (stride == 4) + memcpy(&emu->ymm[i].u128, &vec[i * stride + 2], 16); + } + } + } + for (int i = 0; i < 8; ++i) { + uint8_t scalar = arch->scalar[i]; + if (scalar == 0xFF) continue; + uint64_t raw = vec[(16 + i) * stride]; + int guest = scalar & 0x0F; + if (scalar & 0x10) + emu->xmm[guest].q[0] = raw; + else + emu->xmm[guest].ud[0] = (uint32_t)raw; + } + uint8_t x87 = arch->x87; + while (x87) { + int i = __builtin_ctz(x87); + x87 &= x87 - 1; + int slot = 16 + ((arch->x87_pos >> (i * 3)) & 7); + uint64_t raw = vec[slot * stride]; + switch ((arch->x87_type >> (i * 2)) & 3) { + case LSX_CACHE_ST_D - LSX_CACHE_ST_D: + emu->x87[(emu->top + i) & 7].d = *(double*)&raw; + break; + case LSX_CACHE_ST_F - LSX_CACHE_ST_D: + emu->x87[(emu->top + i) & 7].d = *(float*)&raw; + break; + default: + emu->x87[(emu->top + i) & 7].d = *(int64_t*)&raw; + break; + } + } + uint8_t mmx = arch->mmx; + while (mmx) { + int i = __builtin_ctz(mmx); + mmx &= mmx - 1; + emu->mmx[i].q = vec[(16 + i) * stride] & 0xffffffffffffffffULL; + } + } + } } diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c index 8eaa63b2b..d350c5e7d 100644 --- a/src/dynarec/la64/dynarec_la64_emit_shift.c +++ b/src/dynarec/la64/dynarec_la64_emit_shift.c @@ -2161,11 +2161,10 @@ void emit_shld16c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin { c &= 0x1f; IFX (X_PEND) { - if (c) { - MOV64x(s3, c); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); - } else - ST_H(xZR, xEmu, offsetof(x64emu_t, op2)); + // store fill in the upper half, the deferred handler needs it for the OF flag + SLLI_D(s3, s2, 16); + ORI(s3, s3, c); + ST_W(s3, xEmu, offsetof(x64emu_t, op2)); ST_H(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { @@ -2230,11 +2229,10 @@ void emit_shrd16c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin c &= 0x1f; IFX (X_PEND) { - if (c) { - MOV64x(s3, c); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); - } else - ST_H(xZR, xEmu, offsetof(x64emu_t, op2)); + // store fill in the upper half, the deferred handler needs it for the OF flag + SLLI_D(s3, s2, 16); + ORI(s3, s3, c); + ST_W(s3, xEmu, offsetof(x64emu_t, op2)); ST_H(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { @@ -2295,7 +2293,10 @@ void emit_shld16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, { IFX (X_PEND) { ST_H(s1, xEmu, offsetof(x64emu_t, op1)); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); + // store fill in the upper half, as the deferred handler needs it for count > 16 + SLLI_D(s6, s2, 16); + OR(s6, s6, s3); + ST_W(s6, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { SET_DFNONE(); @@ -2353,7 +2354,10 @@ void emit_shrd16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, { IFX (X_PEND) { ST_H(s1, xEmu, offsetof(x64emu_t, op1)); - ST_H(s3, xEmu, offsetof(x64emu_t, op2)); + // store fill in the upper half, as the deferred handler needs it for count > 16 + SLLI_D(s6, s2, 16); + OR(s6, s6, s3); + ST_W(s6, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { SET_DFNONE(); diff --git a/src/dynarec/la64/dynarec_la64_functions.c b/src/dynarec/la64/dynarec_la64_functions.c index 8d3273f18..26a25d5d4 100644 --- a/src/dynarec/la64/dynarec_la64_functions.c +++ b/src/dynarec/la64/dynarec_la64_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index 3f3335115..1edc27c46 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -48,7 +48,6 @@ uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if ((nextop & 7) == 4) { uint8_t sib = PK(0); - if ((sib & 7) == 4) MARK_LEAF_RSP(LEAF_RSP_REF); if (((sib & 7) != 5) || ((nextop & 0xC0) != 0)) UP32_READ(TO_NAT((sib & 7) + (rex.b << 3))); if ((((sib >> 3) & 7) + (rex.x << 3)) != 4) UP32_READ(TO_NAT(((sib >> 3) & 7) + (rex.x << 3))); } else if (((nextop & 7) != 5) || ((nextop & 0xC0) != 0)) { @@ -379,7 +378,7 @@ void jump_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -401,7 +400,7 @@ void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog_fast); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -415,7 +414,7 @@ void doEnterBlock(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3) LD_D(s1, s1, 0); // load the dynablock pointer ADDI_D(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, 1); - AMADD_W(s2, s3, s1); + AMADD_DB_W(s2, s3, s1); } void doLeaveBlock(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3) @@ -427,7 +426,7 @@ void doLeaveBlock(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3) LD_D(s1, s1, 0); // load the dynablock pointer ADDI_D(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, -1); - AMADD_W(s2, s3, s1); + AMADD_DB_W(s2, s3, s1); } @@ -489,7 +488,7 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 } CLEARIP(); SMEND(); - if (BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if (BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // The JIRL(xRA, ...) form is only for gdb backtraces, but it breaks the // return-address-stack prediction on every block-to-block jump, which is @@ -514,7 +513,7 @@ void ret_to_next(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex) LD_D(xRA, xSP, 0); // native addr LD_D(x6, xSP, 8); // x86 addr ADDI_D(xSP, xSP, 16); // pop - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); @@ -2431,9 +2430,9 @@ static void fpuCacheTransform(dynarec_la64_t* dyn, int ninst, int s1, int s2, in } } } - if (stack_cnt != cache_i2.stack) { - MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack); - int a = stack_cnt - cache_i2.stack; + if (stack_cnt != cache_i2.stack || dyn->lsx.x87stack != cache_i2.x87stack) { + MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d / pending %d -> %d -\n", stack_cnt, cache_i2.stack, dyn->lsx.x87stack, cache_i2.x87stack); + int a = dyn->lsx.x87stack - cache_i2.x87stack; // Add x87stack to emu fpu_stack LD_W(s3, xEmu, offsetof(x64emu_t, fpu_stack)); ADDI_D(s3, s3, a); diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index cb26fd31b..511e30f8f 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -435,8 +435,6 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGd(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (rex.w) \ UP32_WRITE64(r); \ else \ @@ -445,8 +443,6 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGdz(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (!rex.is32bits) \ UP32_WRITE64(r); \ else \ @@ -455,15 +451,11 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGs(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (rex.w) UP32_READ(r); \ } while (0) #define MARKREGsz(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (!rex.is32bits) UP32_READ(r); \ } while (0) @@ -1667,26 +1659,6 @@ static inline int comis_fuse_inverted(int condition) #ifndef SET_HASCALLRET #define SET_HASCALLRET() #endif -#ifndef MARK_LEAF_CALL -#define MARK_LEAF_CALL() \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_CALL_TARGET -#define MARK_LEAF_CALL_TARGET(T) \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_RET -#define MARK_LEAF_RET() \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_RSP -#define MARK_LEAF_RSP(F) \ - do { \ - } while (0) -#endif #ifndef CALLRET_RET #define CALLRET_RET(A) do {if(BOX64DRENV(dynarec_callret)>1) {NOP();}} while(0) #endif @@ -1798,9 +1770,6 @@ static inline int comis_fuse_inverted(int condition) #define native_pass STEPNAME(native_pass) #define updateflags_pass STEPNAME(updateflags_pass) -#define emit_inline_leaf STEPNAME(emit_inline_leaf) -void emit_inline_leaf(dynarec_la64_t* dyn, int ninst); - #define dynarec64_00 STEPNAME(dynarec64_00) #define dynarec64_00_0 STEPNAME(dynarec64_00_0) #define dynarec64_00_1 STEPNAME(dynarec64_00_1) diff --git a/src/dynarec/la64/dynarec_la64_pass0.h b/src/dynarec/la64/dynarec_la64_pass0.h index ab33f177b..e0e13e6d8 100644 --- a/src/dynarec/la64/dynarec_la64_pass0.h +++ b/src/dynarec/la64/dynarec_la64_pass0.h @@ -70,33 +70,26 @@ } else \ dyn->insts[ninst].barrier_maybe = 1 #define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1 -#define MARK_LEAF_CALL() dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_CALL -#define MARK_LEAF_CALL_TARGET(T) \ - do { \ - dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_CALL; \ - dyn->insts[ninst].x64.leaf_target = (uintptr_t)(T); \ - } while (0) -#define MARK_LEAF_RET() dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_RET -#define MARK_LEAF_RSP(F) dyn->insts[ninst].x64.leaf_rsp |= (F) -#define NEW_INST \ - ++dyn->size; \ - dyn->insts[ninst].x64.addr = ip; \ - dyn->lsx.combined1 = dyn->lsx.combined2 = 0; \ - dyn->lsx.swapped = 0; \ - dyn->lsx.barrier = 0; \ - dyn->insts[ninst].up32_read = 0; \ - dyn->insts[ninst].up32_write64 = 0; \ - dyn->insts[ninst].up32_write32 = 0; \ - dyn->insts[ninst].up32_zero = 0; \ - dyn->insts[ninst].up32_skip = 0; \ - dyn->insts[ninst].up32_pending = 0; \ - dyn->insts[ninst].vector_liveness = (vector_liveness_t) { 0 }; \ - dyn->insts[ninst].comis_fusion = -1; \ - dyn->insts[ninst].comis_mark = 0; \ - dyn->insts[ninst].host_call = 0; \ - dyn->insts[ninst].call_window = 0; \ - dyn->insts[ninst].f_entry = dyn->f; \ - if (ninst) { dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr; } \ +#define NEW_INST \ + ++dyn->size; \ + dyn->insts[ninst].x64.addr = ip; \ + dyn->lsx.combined1 = dyn->lsx.combined2 = 0; \ + dyn->lsx.swapped = 0; \ + dyn->lsx.barrier = 0; \ + dyn->insts[ninst].up32_read = 0; \ + dyn->insts[ninst].up32_write64 = 0; \ + dyn->insts[ninst].up32_write32 = 0; \ + dyn->insts[ninst].up32_zero = 0; \ + dyn->insts[ninst].up32_skip = 0; \ + dyn->insts[ninst].up32_pending = 0; \ + dyn->insts[ninst].vector_liveness = (vector_liveness_t) { 0 }; \ + dyn->insts[ninst].comis_fusion = -1; \ + dyn->insts[ninst].comis_mark = 0; \ + dyn->insts[ninst].host_call = 0; \ + dyn->insts[ninst].call_window = 0; \ + dyn->insts[ninst].f_entry = dyn->f; \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem)); \ + if (ninst) { dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr; } \ AREFLAGSNEEDED() #define INST_EPILOG \ diff --git a/src/dynarec/la64/dynarec_la64_pass2.h b/src/dynarec/la64/dynarec_la64_pass2.h index 0223e2cbd..c5d4ebeb4 100644 --- a/src/dynarec/la64/dynarec_la64_pass2.h +++ b/src/dynarec/la64/dynarec_la64_pass2.h @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT #define INIT \ do { \ - if (!dyn->inline_leaf) \ - dyn->native_size = 0; \ + dyn->native_size = 0; \ } while (0) #define ENDPREFIX \ dyn->prefixsize = dyn->native_size; \ diff --git a/src/dynarec/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h index c9721df92..933dec490 100644 --- a/src/dynarec/la64/dynarec_la64_private.h +++ b/src/dynarec/la64/dynarec_la64_private.h @@ -214,9 +214,6 @@ typedef struct dynarec_la64_s { size_t insts_size; // size of the instruction size array (calculated) int callret_size; // size of the array callret_t* callrets; // array of callret return, with NOP / UDF depending if the block is clean or dirty - void* leaf_embeddeds; - uintptr_t inline_native_end; - int16_t inline_rsp; uintptr_t forward; // address of the last end of code while testing forward uintptr_t forward_to; // address of the next jump to (to check if everything is ok) int32_t forward_size; // size at the forward point @@ -231,8 +228,6 @@ typedef struct dynarec_la64_s { uint8_t use_ymm:1; uint8_t no_scalar_renaming:1; uint8_t is_file_mapped:1; - uint8_t inline_leaf:1; - uint8_t inline_is32bits:1; void* gdbjit_block; uint32_t need_x87check; // x87 low precision check int x87round_active; // we are in the middle of x87_setround and x87_restoreround diff --git a/src/dynarec/la64/updateflags_la64_pass.c b/src/dynarec/la64/updateflags_la64_pass.c index 162194adb..1d611c11e 100644 --- a/src/dynarec/la64/updateflags_la64_pass.c +++ b/src/dynarec/la64/updateflags_la64_pass.c @@ -987,19 +987,22 @@ SETMARK(d_ror64); SETMARK(d_shrd16); LD_HU(x1, xEmu, offsetof(x64emu_t, res)); LD_HU(x2, xEmu, offsetof(x64emu_t, op1)); - LD_HU(x3, xEmu, offsetof(x64emu_t, op2)); - ANDI(x4, x3, 0x0f); - ADDI_D(x4, x4, -16); - SUB_D(x4, xZR, x4); - SRL_D(x4, x1, x4); - SRLI_D(x5, x2, 15); + LD_WU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + SRLI_D(x5, x3, 16); + BNEZ(x6, 8 + (cpuext.lbt ? 4 : 0)); + SPILL_EFLAGS(); + BR(xRA); + SRLI_D(x4, x2, 15); XOR(x4, x4, x5); BSTRINS_D(xFlags, x4, F_OF, F_OF); BSTRINS_D(xFlags, xZR, F_AF, F_AF); - BNEZ(x3, 8 + (cpuext.lbt ? 4 : 0)); - SPILL_EFLAGS(); - BR(xRA); - ADDI_D(x4, x3, -1); + ADDI_D(x4, x6, -16); + BGE(xZR, x4, 4 * 4); + ADDI_D(x4, x4, -1); + SRL_D(x4, x5, x4); + B(3 * 4); + ADDI_D(x4, x6, -1); SRL_D(x4, x2, x4); BSTRINS_D(xFlags, x4, F_CF, F_CF); SRLI_D(x4, x1, 15); @@ -1064,10 +1067,17 @@ SETMARK(d_shrd64); SETMARK(d_shld16); LD_HU(x1, xEmu, offsetof(x64emu_t, res)); LD_HU(x2, xEmu, offsetof(x64emu_t, op1)); - LD_HU(x3, xEmu, offsetof(x64emu_t, op2)); - BNEZ(x3, 8); + LD_WU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + BNEZ(x6, 8); BR(xRA); - ADDI_D(x4, x3, -16); + SRLI_D(x5, x3, 16); + ADDI_D(x4, x6, -16); + BGE(xZR, x4, 5 * 4); + SUB_D(x4, xZR, x4); + ADDI_D(x4, x4, 16); + SRL_D(x4, x5, x4); + B(3 * 4); SUB_D(x4, xZR, x4); SRL_D(x4, x2, x4); BSTRINS_D(xFlags, x4, F_CF, F_CF); diff --git a/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c b/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c index b2010bd82..df2e5b4aa 100644 --- a/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c +++ b/src/dynarec/ppc64le/dynarec_ppc64le_emit_shift.c @@ -1890,7 +1890,9 @@ void emit_shld16c(dynarec_ppc64le_t* dyn, int ninst, rex_t rex, int s1, int s2, IFX (X_PEND) { if (c) { MOV64x(s3, c); - STH(s3, offsetof(x64emu_t, op2), xEmu); + SLDI(s4, s2, 16); + OR(s3, s3, s4); + STW(s3, offsetof(x64emu_t, op2), xEmu); } else { LI(s3, 0); STH(s3, offsetof(x64emu_t, op2), xEmu); @@ -1959,7 +1961,9 @@ void emit_shld16(dynarec_ppc64le_t* dyn, int ninst, int s1, int s2, int s3, int { IFX (X_PEND) { STH(s1, offsetof(x64emu_t, op1), xEmu); - STH(s3, offsetof(x64emu_t, op2), xEmu); + SLDI(s5, s2, 16); + OR(s5, s5, s3); + STW(s5, offsetof(x64emu_t, op2), xEmu); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { SET_DFNONE(); @@ -2022,7 +2026,9 @@ void emit_shrd16c(dynarec_ppc64le_t* dyn, int ninst, rex_t rex, int s1, int s2, IFX (X_PEND) { if (c) { MOV64x(s3, c); - STH(s3, offsetof(x64emu_t, op2), xEmu); + SLDI(s4, s2, 16); + OR(s3, s3, s4); + STW(s3, offsetof(x64emu_t, op2), xEmu); } else { LI(s3, 0); STH(s3, offsetof(x64emu_t, op2), xEmu); @@ -2088,7 +2094,9 @@ void emit_shrd16(dynarec_ppc64le_t* dyn, int ninst, int s1, int s2, int s3, int { IFX (X_PEND) { STH(s1, offsetof(x64emu_t, op1), xEmu); - STH(s3, offsetof(x64emu_t, op2), xEmu); + SLDI(s5, s2, 16); + OR(s5, s5, s3); + STW(s5, offsetof(x64emu_t, op2), xEmu); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { SET_DFNONE(); diff --git a/src/dynarec/ppc64le/dynarec_ppc64le_functions.c b/src/dynarec/ppc64le/dynarec_ppc64le_functions.c index 62c466e14..15794c5d0 100644 --- a/src/dynarec/ppc64le/dynarec_ppc64le_functions.c +++ b/src/dynarec/ppc64le/dynarec_ppc64le_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h b/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h index 3514c6adf..4e8f8d276 100644 --- a/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h +++ b/src/dynarec/ppc64le/dynarec_ppc64le_pass0.h @@ -64,6 +64,7 @@ dyn->v.combined1 = dyn->v.combined2 = 0;\ dyn->v.swapped = 0; dyn->v.barrier = 0; \ dyn->insts[ninst].f_entry = dyn->f; \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem));\ if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;} \ AREFLAGSNEEDED() diff --git a/src/dynarec/rv64/dynarec_rv64_00_0.c b/src/dynarec/rv64/dynarec_rv64_00_0.c index 2aabe08f2..116e83ae0 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_0.c +++ b/src/dynarec/rv64/dynarec_rv64_00_0.c @@ -65,7 +65,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; @@ -83,7 +83,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("ADD Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; @@ -99,6 +99,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x05: INST_NAME("ADD EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); break; @@ -155,7 +156,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_or32(dyn, ninst, rex, ed, gd, x3, x4); WBACK; break; @@ -173,7 +174,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("OR Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_or32(dyn, ninst, rex, gd, ed, x3, x4); break; @@ -189,6 +190,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x0D: INST_NAME("OR EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; @@ -255,7 +257,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); WBACK; break; @@ -280,7 +282,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6); break; @@ -298,6 +300,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("ADC EAX, Id"); READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; MOV64xw(x1, i64); emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); @@ -364,7 +367,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; @@ -389,7 +392,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; @@ -407,6 +410,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("SBB EAX, Id"); READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; MOV64xw(x2, i64); emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); @@ -465,7 +469,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_and32(dyn, ninst, rex, ed, gd, x3, x4); WBACK; break; @@ -482,7 +486,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AND Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_and32(dyn, ninst, rex, gd, ed, x3, x4); break; @@ -498,6 +502,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x25: INST_NAME("AND EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_and32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; @@ -516,7 +521,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; @@ -534,7 +539,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("SUB Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5); break; @@ -550,6 +555,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2D: INST_NAME("SUB EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_sub32c(dyn, ninst, rex, xRAX, i64, x2, x3, x4, x5); break; @@ -571,7 +577,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; GETGD; - GETED(0); + GETEDsd(0); emit_xor32(dyn, ninst, rex, ed, gd, x3, x4); if (ed != gd) { WBACK; @@ -591,7 +597,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("XOR Gd, Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); emit_xor32(dyn, ninst, rex, gd, ed, x3, x4); break; @@ -607,6 +613,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x35: INST_NAME("XOR EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + MARKREGsd(xRAX); i64 = F32S; emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; @@ -661,6 +668,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("CMP EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); i64 = F32S; + MARKREGs(xRAX); if (i64) { MOV64x(x2, i64); emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6); diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c index ec23eeba1..fe786fdc9 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_1.c +++ b/src/dynarec/rv64/dynarec_rv64_00_1.c @@ -63,6 +63,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("INC Reg (32bits)"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); gd = TO_NAT(opcode & 7); + MARKREGsd(gd); emit_inc32(dyn, ninst, rex, gd, x1, x2, x3, x4); break; case 0x48: @@ -76,6 +77,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("DEC Reg (32bits)"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); gd = TO_NAT(opcode & 7); + MARKREGsd(gd); emit_dec32(dyn, ninst, rex, gd, x1, x2, x3, x4); break; case 0x50: @@ -89,7 +91,9 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("PUSH reg"); SCRATCH_USAGE(0); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); - PUSH1z(gd); + MARKREGsz(gd); + if (!rex.is32bits) UP32_READ(xRSP); + PUSH1mz(gd); break; case 0x58: case 0x59: @@ -102,21 +106,40 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("POP reg"); SCRATCH_USAGE(0); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); - POP1z(gd); + if (!rex.is32bits) UP32_READ(xRSP); + MARKREGdz(gd); + POP1mz(gd); break; case 0x60: if (rex.is32bits) { INST_NAME("PUSHAD"); + dyn->insts[ninst].rsp_class = RSP_CLASS_PUSH; + dyn->insts[ninst].rsp_span = 32; ZEXTW2(x1, xRSP); - PUSH1_32(xRAX); - PUSH1_32(xRCX); - PUSH1_32(xRDX); - PUSH1_32(xRBX); - PUSH1_32(x1); - PUSH1_32(xRBP); - PUSH1_32(xRSI); - PUSH1_32(xRDI); + if (dyn->insts[ninst].rsp_merge && !(cpuext.xtheadmemidx && dyn->insts[ninst].rsp_flush && !dyn->insts[ninst].rsp_entry)) { + int entry = dyn->insts[ninst].rsp_entry; + if (entry) ADDIW(x1, x1, entry); + SW(xRAX, xRSP, entry - 4); + SW(xRCX, xRSP, entry - 8); + SW(xRDX, xRSP, entry - 12); + SW(xRBX, xRSP, entry - 16); + SW(x1, xRSP, entry - 20); + SW(xRBP, xRSP, entry - 24); + SW(xRSI, xRSP, entry - 28); + SW(xRDI, xRSP, entry - 32); + if (dyn->insts[ninst].rsp_flush) + ADDI(xRSP, xRSP, dyn->insts[ninst].rsp_flush); + } else { + PUSH1_32(xRAX); + PUSH1_32(xRCX); + PUSH1_32(xRDX); + PUSH1_32(xRBX); + PUSH1_32(x1); + PUSH1_32(xRBP); + PUSH1_32(xRSI); + PUSH1_32(xRDI); + } SMWRITE(); } else { INST_NAME("Illegal 60"); @@ -135,15 +158,45 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x61: if (rex.is32bits) { INST_NAME("POPAD"); + dyn->insts[ninst].rsp_class = RSP_CLASS_POP; + dyn->insts[ninst].rsp_span = 32; SMREAD(); - POP1_32(xRDI); - POP1_32(xRSI); - POP1_32(xRBP); - POP1_32(x1); - POP1_32(xRBX); - POP1_32(xRDX); - POP1_32(xRCX); - POP1_32(xRAX); + if (dyn->insts[ninst].rsp_merge && !(cpuext.xtheadmemidx && dyn->insts[ninst].rsp_flush && !dyn->insts[ninst].rsp_entry)) { + int entry = dyn->insts[ninst].rsp_entry; + LWU(xRDI, xRSP, entry + 0); + LWU(xRSI, xRSP, entry + 4); + LWU(xRBP, xRSP, entry + 8); + LWU(x1, xRSP, entry + 12); + LWU(xRBX, xRSP, entry + 16); + LWU(xRDX, xRSP, entry + 20); + LWU(xRCX, xRSP, entry + 24); + LWU(xRAX, xRSP, entry + 28); + if (dyn->insts[ninst].rsp_flush) + ADDI(xRSP, xRSP, dyn->insts[ninst].rsp_flush); + } else { + POP1_32(xRDI); + POP1_32(xRSI); + POP1_32(xRBP); + POP1_32(x1); + POP1_32(xRBX); + POP1_32(xRDX); + POP1_32(xRCX); + POP1_32(xRAX); + } + UP32_WRITE32(xRDI); + UP32_ZERO(xRDI); + UP32_WRITE32(xRSI); + UP32_ZERO(xRSI); + UP32_WRITE32(xRBP); + UP32_ZERO(xRBP); + UP32_WRITE32(xRBX); + UP32_ZERO(xRBX); + UP32_WRITE32(xRDX); + UP32_ZERO(xRDX); + UP32_WRITE32(xRCX); + UP32_ZERO(xRCX); + UP32_WRITE32(xRAX); + UP32_ZERO(xRAX); } else { INST_NAME("Illegal 61"); if (BOX64DRENV(dynarec_safeflags) > 1) { @@ -199,7 +252,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { INST_NAME("MOVSXD Gd, Ed"); nextop = F8; - GETGD; + GETGDd; SCRATCH_USAGE(0); if (rex.w) { if (MODREG) { // reg <= reg @@ -222,18 +275,19 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x68: INST_NAME("PUSH Id"); + if (!rex.is32bits) UP32_READ(xRSP); i64 = F32S; if (PK(0) == 0xC3) { MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n"); TABLE64(x3, addr - 4); LW(x1, x3, 0); - PUSH1z(x1); + PUSH1mz(x1); } else { if (!i64) { - PUSH1z(xZR); + PUSH1mz(xZR); } else { MOV64z(x3, i64); - PUSH1z(x3); + PUSH1mz(x3); } } break; @@ -241,7 +295,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("IMUL Gd, Ed, Id"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; + GETGDd; GETED(4); i64 = F32S; MOV64x(x4, i64); @@ -284,7 +338,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTW2(gd, x5); } else { MULxw(gd, ed, x4); - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } } IFX (X_SF) { @@ -296,19 +350,20 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x6A: INST_NAME("PUSH Ib"); + if (!rex.is32bits) UP32_READ(xRSP); i64 = F8S; if (!i64) { - PUSH1z(xZR); + PUSH1mz(xZR); } else { MOV64z(x3, i64); - PUSH1z(x3); + PUSH1mz(x3); } break; case 0x6B: INST_NAME("IMUL Gd, Ed, Ib"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; + GETGDd; GETED(1); i64 = F8S; MOV64x(x4, i64); @@ -351,7 +406,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTW2(gd, x5); } else { MULW(gd, ed, x4); - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } } IFX (X_SF) { @@ -398,7 +453,6 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int #define GO(GETFLAGS, NO, YES, NATNO, NATYES, F) \ READFLAGS_FUSION(F, x1, x2, x3, x4, x5); \ i8 = F8S; \ - BARRIER(BARRIER_MAYBE); \ JUMP(addr + i8, 1); \ if (!dyn->insts[ninst].nat_flags_fusion) { \ GETFLAGS; \ diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index 464d858f8..3a288a582 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -137,7 +137,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("ADD Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -152,7 +152,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("OR Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -168,7 +168,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -185,7 +185,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } READFLAGS(X_CF); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -201,7 +201,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("AND Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -216,7 +216,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("SUB Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -231,7 +231,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("XOR Ed, Ib"); } SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED((opcode == 0x81) ? 4 : 1); + GETEDsd((opcode == 0x81) ? 4 : 1); if (opcode == 0x81) i64 = F32S; else @@ -327,7 +327,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("(LOCK) XCHG Ed, Gd"); nextop = F8; if (MODREG) { - GETGD; + GETGDsd; GETED(0); MVxw(x3, gd); MVxw(gd, ed); @@ -400,7 +400,9 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGD; if (MODREG) { // reg <= reg SCRATCH_USAGE(0); - MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd); + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); + MVxw(ed, gd); } else { // mem <= reg IF_UNALIGNED(ip) { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, (1 << (2 + rex.w)) - 1, 0); @@ -467,7 +469,8 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x8B: INST_NAME("MOV Gd, Ed"); nextop = F8; - GETGD; + GETGDd; + if (!rex.w) UP32_ZERO(gd); SCRATCH_USAGE(0); if (MODREG) { MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3))); @@ -496,7 +499,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x8D: INST_NAME("LEA Gd, Ed"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { // reg <= reg? that's an invalid operation DEFAULT; } else { // mem <= reg @@ -508,8 +511,9 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTW2(gd, ed); else MVxw(gd, ed); + if (!rex.w) UP32_ZERO(gd); } else if (!rex.w && !rex.is32bits) { - ZEROUP(gd); // truncate the higher 32bits as asked + ZEROUP_RESULT(gd); // truncate the higher 32bits as asked } } break; @@ -536,8 +540,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x8F: INST_NAME("POP Ed"); nextop = F8; + MARKREGsdz(xRSP); if (MODREG) { - POP1z(TO_NAT((nextop & 7) + (rex.b << 3))); + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGdz(ed); + POP1z(ed); } else { POP1z(x2); // so this can handle POP [ESP] and maybe some variant too addr = geted(dyn, addr, ninst, nextop, &ed, x3, x1, &fixedaddress, rex, NULL, 1, 0); @@ -564,6 +571,8 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("NOP"); } else { INST_NAME("XCHG EAX, Reg"); + MARKREGsd(gd); + MARKREGsd(xRAX); MVxw(x2, xRAX); MVxw(xRAX, gd); MVxw(gd, x2); @@ -572,20 +581,24 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x98: INST_NAME("CWDE"); if (rex.w) { + MARKREGd(xRAX); SEXT_W(xRAX, xRAX); } else { + MARKREGd(xRAX); SEXTH(xRAX, xRAX); - ZEROUP(xRAX); + if (NEED_ZEROUP(xRAX)) ZEROUP_RESULT(xRAX); } break; case 0x99: INST_NAME("CDQ"); + MARKREGd(xRDX); + MARKREGs(xRAX); if (rex.w) { SRAI(xRDX, xRAX, 63); } else { SLLI(xRDX, xRAX, 32); SRAI(xRDX, xRDX, 63); - ZEROUP(xRDX); + if (NEED_ZEROUP(xRDX)) ZEROUP_RESULT(xRDX); } break; case 0x9B: @@ -594,12 +607,14 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x9C: INST_NAME("PUSHF"); READFLAGS(X_ALL); + if (!rex.is32bits) UP32_READ(xRSP); FLAGS_ADJUST_TO11(x3, xFlags, x2); PUSH1z(x3); break; case 0x9D: INST_NAME("POPF"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + if (!rex.is32bits) UP32_READ(xRSP); POP1z(xFlags); FLAGS_ADJUST_FROM11(xFlags, xFlags, x2); MOV32w(x1, 0x3E7FF7); @@ -657,6 +672,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xA1: INST_NAME("MOV EAX, Od"); + MARKREGd(xRAX); if (rex.is32bits && rex.is67) u64 = F16S; else if (rex.is32bits || rex.is67) @@ -691,6 +707,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xA3: INST_NAME("MOV Od, EAX"); + MARKREGs(xRAX); if (rex.is32bits && rex.is67) u64 = F16S; else if (rex.is32bits || rex.is67) @@ -707,8 +724,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITELOCK(lock); break; case 0xA4: + UP32_READ(xRSI); + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP MOVSB"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRSI); @@ -766,8 +786,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xA5: + UP32_READ(xRSI); + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP MOVSD"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRSI); @@ -807,9 +830,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xA6: + UP32_READ(xRSI); + UP32_READ(xRDI); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ CMPSB"); } else { @@ -872,9 +898,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xA7: + UP32_READ(xRSI); + UP32_READ(xRDI); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ CMPSD"); } else { @@ -947,12 +976,16 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("TEST EAX, Id"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); i64 = F32S; + MARKREGs(xRAX); MOV64xw(x2, i64); emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); break; case 0xAA: + UP32_READ(xRDI); + UP32_READ(xRAX); if (rex.rep) { INST_NAME("REP STOSB"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRDI); @@ -1001,8 +1034,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xAB: + UP32_READ(xRDI); + UP32_READ(xRAX); if (rex.rep) { INST_NAME("REP STOSD"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRDI); @@ -1033,6 +1069,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xAC: + UP32_READ(xRSI); if (rex.rep) { DEFAULT; } else { @@ -1048,6 +1085,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAD: + UP32_READ(xRSI); if (rex.rep) { DEFAULT; } else { @@ -1061,9 +1099,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAE: + UP32_READ(xRDI); + UP32_READ(xRAX); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ SCASB"); } else { @@ -1120,9 +1161,12 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAF: + UP32_READ(xRDI); + UP32_READ(xRAX); switch (rex.rep) { case 1: case 2: + UP32_READ(xRCX); if (rex.rep == 1) { INST_NAME("REPNZ SCASD"); } else { @@ -1224,13 +1268,15 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xBF: INST_NAME("MOV Reg, Id"); gd = TO_NAT((opcode & 7) + (rex.b << 3)); - SCRATCH_USAGE(0); + MARKREGd(gd); if (rex.w) { u64 = F64; - MOV64x(gd, u64); + MOV64xss(gd, u64, x1, x2); } else { + SCRATCH_USAGE(0); u32 = F32; MOV32w(gd, u32); + UP32_ZERO(gd); } break; default: diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 8c8f76de8..c69131e9b 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -181,14 +181,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS((!BOX64ENV(cputype) && (u8 > 1) && MODREG) ? X_CF : (X_OF | X_CF), SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -201,14 +201,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS((!BOX64ENV(cputype) && (u8 > 1) && MODREG) ? X_CF : (X_OF | X_CF), SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -221,7 +221,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (u8) { READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); u8 = (F8) & (rex.w ? 0x3f : 0x1f); emit_rcl32c(dyn, ninst, rex, ed, u8, x3, x4, x5); WBACK; @@ -238,7 +238,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (u8) { READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); u8 = (F8) & (rex.w ? 0x3f : 0x1f); emit_rcr32c(dyn, ninst, rex, ed, u8, x3, x4, x5); WBACK; @@ -256,14 +256,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4, x5); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -276,14 +276,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -296,14 +296,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // flags are not affected if count is 0, we make it a nop if possible. if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); F8; emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); WBACK; } else { if (MODREG && !rex.w) { GETED(1); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } else { FAKEED; } @@ -322,6 +322,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } BARRIER(BARRIER_FLOAT); u16 = F16; + if (!rex.is32bits) UP32_READ(xRSP); POP1z(xRIP); if (u16 < 0x7ff) ADDIz(xRSP, xRSP, u16); @@ -340,6 +341,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } BARRIER(BARRIER_FLOAT); + if (!rex.is32bits) UP32_READ(xRSP); POP1z(xRIP); ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; @@ -400,8 +402,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (eb2) { // load a mask to x3 (ffffffffffff00ff) - LUI(x3, 0xffff0); - ORI(x3, x3, 0xff); + MOV64x(x3, 0xFFFFFFFFFFFF00FF); // apply mask AND(eb1, eb1, x3); if (u8) { @@ -474,6 +475,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xC8: INST_NAME("ENTER Iw, Ib"); + if (!rex.is32bits) { + UP32_READ(xRSP); + UP32_READ(xRBP); + } u16 = F16; u8 = (F8) & 0x1f; if (u8) { @@ -498,6 +503,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC9: INST_NAME("LEAVE"); + MARKREGsz(xRBP); MVz(xRSP, xRBP); POP1z(xRBP); break; @@ -506,6 +512,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u16 = F16; READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); + if (!rex.is32bits) UP32_READ(xRSP); if (rex.w) { POP1(xRIP); POP1(x3); @@ -528,6 +535,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("FAR RET"); READFLAGS(X_PEND); BARRIER(BARRIER_FLOAT); + if (!rex.is32bits) UP32_READ(xRSP); if (rex.w) { POP1(xRIP); POP1(x3); @@ -839,7 +847,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0: INST_NAME("ROL Ed, 1"); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_rol32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -847,7 +855,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 1: INST_NAME("ROR Ed, 1"); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_ror32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -856,7 +864,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("RCL Ed, 1"); READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_rcl32c(dyn, ninst, rex, ed, 1, x3, x4, x5); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -865,7 +873,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("RCR Ed, 1"); READFLAGS(X_CF); SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_rcr32c(dyn, ninst, rex, ed, 1, x3, x4, x5); WBACK; if (!wback && !rex.w) ZEROUP(ed); @@ -874,21 +882,21 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 6: INST_NAME("SHL Ed, 1"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined - GETED(0); + GETEDsd(0); emit_shl32c(dyn, ninst, rex, ed, 1, x3, x4, x5); WBACK; break; case 5: INST_NAME("SHR Ed, 1"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined - GETED(0); + GETEDsd(0); emit_shr32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; break; case 7: INST_NAME("SAR Ed, 1"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined - GETED(0); + GETEDsd(0); emit_sar32c(dyn, ninst, rex, ed, 1, x3, x4); WBACK; break; @@ -906,8 +914,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_OF | X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); // removed PENDING on purpose - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_rol32(dyn, ninst, rex, ed, x6, x3, x4); @@ -919,8 +927,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_OF | X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); // removed PENDING on purpose - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_ror32(dyn, ninst, rex, ed, x6, x3, x4); @@ -934,8 +942,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_rcl32(dyn, ninst, rex, ed, x6, x3, x4, x5); @@ -949,8 +957,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int READFLAGS(X_CF); } SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); - GETED(0); - if (!wback && !rex.w) ZEROUP(ed); + GETEDsd(0); + if (!wback && !rex.w) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x6, xZR); emit_rcr32(dyn, ninst, rex, ed, x6, x3, x4, x5); @@ -965,7 +973,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined if (!dyn->insts[ninst].x64.gen_flags) { - GETED(0); + GETEDsd(0); if (rex.w) SLL(ed, ed, xRCX); else @@ -994,7 +1002,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined if (!dyn->insts[ninst].x64.gen_flags) { - GETED(0); + GETEDsd(0); if (rex.w) SRL(ed, ed, xRCX); else @@ -1022,8 +1030,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); - GETED(0); - if (!rex.w && MODREG) { ZEROUP(ed); } + GETEDsd(0); + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } CBZ_NEXT(x3); emit_sar32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; @@ -1039,7 +1047,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 = F8; MOV32w(x2, u8); CALL(const_aam16, x1, x1, x2); - ANDI(x1, x1, 0xffff); + ZEXTH(x1, x1); SRLI(x3, xRAX, 16); SLLI(x3, x3, 16); OR(xRAX, x3, x1); @@ -1060,11 +1068,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (rex.is32bits) { INST_NAME("AAD Ib"); SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); - ANDI(x1, xRAX, 0xffff); + ZEXTH(x1, xRAX); u8 = F8; MOV32w(x2, u8); CALL(const_aad16, x1, x1, x2); - ANDI(x1, x1, 0xffff); + ZEXTH(x1, x1); SRLI(x3, xRAX, 16); SLLI(x3, x3, 16); OR(xRAX, x3, x1); @@ -1105,6 +1113,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xD7: INST_NAME("XLAT"); + UP32_READ(xRBX); ANDI(x1, xRAX, 0xff); if (rex.seg) { grab_segdata(dyn, addr, ninst, x2, rex.seg); @@ -1141,7 +1150,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int addr = dynarec64_DF(dyn, addr, ip, ninst, rex, ok, need_epilog); break; #define GO(Z, R) \ - BARRIER(BARRIER_MAYBE); \ JUMP(addr + i8, 1); \ if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) { \ /* out of the block */ \ @@ -1181,6 +1189,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int CBNZ_NEXT(x1); GO(0, x3); } else { + UP32_READ(xRCX); ADDIy(xRCX, xRCX, -1); ANDI(x1, xFlags, 1 << F_ZF); CBNZ_NEXT(x1); @@ -1199,6 +1208,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int CBZ_NEXT(x1); GO(0, x3); } else { + UP32_READ(xRCX); ADDIy(xRCX, xRCX, -1); ANDI(x1, xFlags, 1 << F_ZF); CBZ_NEXT(x1); @@ -1214,6 +1224,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INSH(xRCX, x3, x5, x6, 1, 0); GO(0, x3); } else { + UP32_READ(xRCX); ADDIy(xRCX, xRCX, -1); GO(0, xRCX); } @@ -1225,9 +1236,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ZEXTH(x3, xRCX); GO(1, x3); } else if (rex.is32bits || rex.is67) { + UP32_READ(xRCX); ADDIy(x3, xRCX, 0); GO(1, x3); } else { + UP32_READ(xRCX); GO(1, xRCX); } break; @@ -1310,11 +1323,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 1: // this is call to next step, so just push the return address to the stack - if (dyn->need_reloc) { - TABLE64(x2, addr); - } else { - MOV64x(x2, addr); - } + GETRETADDR(addr, x2, x3); PUSH1z(x2); break; default: @@ -1324,12 +1333,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags to "dont'care" state } // regular call - if (dyn->need_reloc) { - TABLE64(x2, addr); - } else { - MOV64x(x2, addr); - } - fpu_purgecache(dyn, ninst, 0, x1, x3, x4); + GETRETADDR(addr, x2, x3); + BARRIER(BARRIER_FLOAT); PUSH1z(x2); int can_continue = (addr < (dyn->start + dyn->isize)); if (BOX64DRENV(dynarec_callret)) { @@ -1377,6 +1382,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int MOV64x(x4, j64); } LD(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -1400,7 +1407,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int JUMP((uintptr_t)getAlternate((void*)j64), 0); if (dyn->insts[ninst].x64.jmp_insts == -1) { // out of the block - fpu_purgecache(dyn, ninst, 1, x1, x2, x3); + BARRIER(BARRIER_FLOAT); + fpu_purgecache(dyn, ninst, 0, x1, x2, x3); jump_to_next(dyn, (uintptr_t)getAlternate((void*)j64), 0, ninst, rex.is32bits); } else { // inside the block @@ -1443,6 +1451,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (box64_unittest_mode) { // HLT in unittest mode is an exit READFLAGS(X_ALL); BARRIER(BARRIER_FLOAT); + fpu_purgecache(dyn, ninst, 0, x1, x2, x3); MOV32w(x1, 1); SW(x1, xEmu, offsetof(x64emu_t, quit)); } else { @@ -1516,7 +1525,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int OR(xFlags, xFlags, x3); } } - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(xRAX, xRAX, x2); ZEXTH(x1, x1); OR(xRAX, xRAX, x1); @@ -1545,7 +1554,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int OR(xFlags, xFlags, x3); } } - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(xRAX, xRAX, x2); ZEXTH(x1, x1); OR(xRAX, xRAX, x1); @@ -1559,6 +1568,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("DIV Eb"); MESSAGE(LOG_DUMP, "Need Optimization\n"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + CHECK_DFNONE(1); GETEB(x1, 0); ZEXTH(x2, xRAX); if (BOX64ENV(dynarec_div0)) { @@ -1573,7 +1583,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } DIVUW(x3, x2, ed); REMUW(x4, x2, ed); - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); AND(xRAX, xRAX, x5); ANDI(x3, x3, 0xff); OR(xRAX, xRAX, x3); @@ -1612,16 +1622,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 2: INST_NAME("NOT Ed"); - GETED(0); + GETEDsd(0); XORI(ed, ed, -1); if (!rex.w && MODREG) - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); WBACK; break; case 3: INST_NAME("NEG Ed"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_neg32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; break; @@ -1632,6 +1642,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); GETED(0); if (rex.w) { + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); if (ed == xRDX) gd = x3; else @@ -1640,6 +1653,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int MUL(xRAX, xRAX, ed); if (gd != xRDX) { MV(xRDX, gd); } } else { + MARKREGd(xRAX); + MARKREGd(xRDX); ZEXTW2(x3, xRAX); if (MODREG) { ZEXTW2(x4, ed); @@ -1674,6 +1689,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); GETSED(0); if (rex.w) { + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); if (ed == xRDX) gd = x3; else @@ -1682,6 +1700,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int MUL(xRAX, xRAX, ed); if (gd != xRDX) { MV(xRDX, gd); } } else { + MARKREGd(xRAX); + MARKREGd(xRDX); ADDIW(x3, xRAX, 0); // sign extend 32bits-> 64bits MUL(xRDX, x3, ed); // 64 <- 32x32 ZEXTW2(xRAX, xRDX); @@ -1711,6 +1731,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("DIV Ed"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); + CHECK_DFNONE(1); + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); + MARKREGs(xRDX); if (!rex.w) { GETED(0); if (ninst && (nextop == 0xF0) @@ -1744,7 +1769,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int DIVU(x2, x3, ed); REMU(xRDX, x3, ed); ZEXTW2(xRAX, x2); - ZEROUP(xRDX); + if (NEED_ZEROUP(xRDX)) ZEROUP_RESULT(xRDX); } } else { if (ninst @@ -1798,6 +1823,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); } + CHECK_DFNONE(1); + MARKREGd(xRAX); + MARKREGd(xRDX); + MARKREGs(xRAX); + MARKREGs(xRDX); if (!rex.w) { GETSED(0); if (BOX64ENV(dynarec_div0)) { @@ -1816,7 +1846,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int DIV(x2, x3, ed); REM(xRDX, x3, ed); ZEXTW2(xRAX, x2); - ZEROUP(xRDX); + if (NEED_ZEROUP(xRDX)) ZEROUP_RESULT(xRDX); } else { if (ninst && dyn->insts && dyn->insts[ninst - 1].x64.addr @@ -1918,14 +1948,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0: // INC Ed INST_NAME("INC Ed"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_inc32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; break; case 1: // DEC Ed INST_NAME("DEC Ed"); SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION); - GETED(0); + GETEDsd(0); emit_dec32(dyn, ninst, rex, ed, x3, x4, x5, x6); WBACK; break; @@ -1980,6 +2010,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -2050,6 +2082,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP); TABLE64_(x4, j64); LD(x4, x4, 0); + if (BOX64DRENV(dynarec_callret) >= 3) + doLeaveBlock(dyn, ninst, x5, x6, x7); BR(x4); } CLEARIP(); @@ -2084,6 +2118,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 6: // Push Ed INST_NAME("PUSH Ed"); + if (!rex.is32bits) UP32_READ(xRSP); GETEDz(0); PUSH1z(ed); break; diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 09d7f00f6..eef0a51e1 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -267,14 +267,18 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0x13: - INST_NAME("MOVLPS Ex,Gx"); nextop = F8; - GETGX(); - GETEX(x2, 0, 1); - LD(x3, gback, gdoffset + 0); - SD(x3, wback, fixedaddress + 0); - if (!MODREG) + if (MODREG) { + INST_NAME("Illegal 0F 13"); + UDF(); + } else { + INST_NAME("MOVLPS Ex,Gx"); + GETGX(); + GETEX(x2, 0, 1); + LD(x3, gback, gdoffset + 0); + SD(x3, wback, fixedaddress + 0); SMWRITE2(); + } break; case 0x14: INST_NAME("UNPCKLPS Gx,Ex"); @@ -315,14 +319,18 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SD(x4, gback, gdoffset + 8); break; case 0x17: - INST_NAME("MOVHPS Ex,Gx"); nextop = F8; - GETGX(); - GETEX(x2, 0, 1); - LD(x4, gback, gdoffset + 8); - SD(x4, wback, fixedaddress + 0); - if (!MODREG) + if (MODREG) { + INST_NAME("Illegal 0F 17"); + UDF(); + } else { + INST_NAME("MOVHPS Ex,Gx"); + GETGX(); + GETEX(x2, 0, 1); + LD(x4, gback, gdoffset + 8); + SD(x4, wback, fixedaddress + 0); SMWRITE2(); + } break; case 0x18: nextop = F8; @@ -420,6 +428,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } @@ -443,6 +452,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } @@ -501,6 +511,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SLLI(x3, x3, box64_rdtsc_shift); } SRLI(xRDX, x3, 32); + MARKREGd(xRAX); + MARKREGd(xRDX); ZEXTW2(xRAX, x3); // wipe upper part break; case 0x38: @@ -890,7 +902,6 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni d1 = fpu_get_scratch(dyn); q1 = fpu_get_scratch(dyn); int vz = fpu_get_scratch(dyn); - VXOR_VV(vz, vz, vz, 1); switch (u8) { case 0xC8: VROR_VI(d0, v0, 2, 1); @@ -901,13 +912,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xC9: VSLIDEDOWN_VI(d0, v1, 2, 1); - VSLIDEUP_VI(d0, vz, 2, 1); VSLIDEUP_VI(d0, v0, 2, 1); VXOR_VV(v0, v0, d0, 1); break; case 0xCA: - VSLIDEUP_VI(d0, vz, 0, 1); - VSLIDEUP_VI(d0, v1, 1, 1); + VXOR_VV(vz, vz, vz, 1); + VSLIDE1UP_VX(d0, v1, xZR, 1); VXOR_VV(d0, d0, v0, 1); VROR_VI(v0, d0, 31, 1); VSLIDEDOWN_VI(d1, v0, 3, 1); @@ -926,6 +936,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni VADD_VV(v0, v0, d1, 1); break; case 0xCD: + VXOR_VV(vz, vz, vz, 1); VSLIDEDOWN_VI(d0, v1, 2, 1); VSLIDEUP_VI(d0, vz, 2, 1); VROR_VI(d1, d0, 17, 1); @@ -988,7 +999,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xF0: INST_NAME("MOVBE Gd, Ed"); nextop = F8; - GETGD; + GETGDd; SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); LDxw(gd, ed, fixedaddress); @@ -1038,30 +1049,127 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } break; - case 0xCC: + case 0xCC: { INST_NAME("SHA1RNDS4 Gx, Ex, Ib"); nextop = F8; + if (!cpuext.vector || !cpuext.zvbb) { + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + sse_reflect_reg(dyn, ninst, x6, ed); + ADDI(x2, xEmu, offsetof(x64emu_t, xmm[ed])); + wback = x2; + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1); + if (wback != x2 || fixedaddress) { + ADDI(x2, wback, fixedaddress); + wback = x2; + } + } + u8 = F8; + GETG; + sse_forget_reg(dyn, ninst, x6, gd); + ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd])); + MOV32w(x3, u8); + CALL4(const_sha1rnds4, -1, x1, wback, x3, 0); + break; + } + static const uint32_t sha1_k[4] = { + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 + }; + int qA = fpu_get_scratch(dyn); + int qB = fpu_get_scratch(dyn); + int qC = fpu_get_scratch(dyn); + int qD = fpu_get_scratch(dyn); + int qT = fpu_get_scratch(dyn); + int qU = fpu_get_scratch(dyn); + int qM = fpu_get_scratch(dyn); + GETG; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); - sse_reflect_reg(dyn, ninst, x6, ed); - ADDI(x2, xEmu, offsetof(x64emu_t, xmm[ed])); - wback = x2; + u8 = F8; + q0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW32); + q1 = sse_get_reg_vector(dyn, ninst, x1, ed, 0, VECTOR_SEW32); + VMV_V_V(qM, q1); } else { SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1); - // the address is passed as an argument to the helper, so it must not stay in a guest register - if (wback != x2 || fixedaddress) { - ADDI(x2, wback, fixedaddress); - wback = x2; - } + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + u8 = F8; + q0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW32); + VLE32_V(qM, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); } - u8 = F8; - GETG; - sse_forget_reg(dyn, ninst, x6, gd); - ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd])); - MOV32w(x3, u8); - CALL4(const_sha1rnds4, -1, x1, wback, x3, 0); + MOV32w(x7, sha1_k[u8 & 3]); + VADD_VX(qM, qM, x7, VECTOR_UNMASKED); + VSLIDEDOWN_VI(qA, q0, 3, VECTOR_UNMASKED); + VSLIDEDOWN_VI(qB, q0, 2, VECTOR_UNMASKED); + VSLIDEDOWN_VI(qC, q0, 1, VECTOR_UNMASKED); + +#define SHA1_F(dst, vb, vc, vd, tmp) \ + do { \ + switch (u8 & 3) { \ + case 0: \ + VXOR_VV(tmp, vc, vd, VECTOR_UNMASKED); \ + VAND_VV(tmp, vb, tmp, VECTOR_UNMASKED); \ + VXOR_VV(dst, tmp, vd, VECTOR_UNMASKED); \ + break; \ + case 1: \ + case 3: \ + VXOR_VV(dst, vb, vc, VECTOR_UNMASKED); \ + VXOR_VV(dst, dst, vd, VECTOR_UNMASKED); \ + break; \ + default: \ + VXOR_VV(dst, vb, vc, VECTOR_UNMASKED); \ + VAND_VV(dst, dst, vd, VECTOR_UNMASKED); \ + VAND_VV(tmp, vb, vc, VECTOR_UNMASKED); \ + VXOR_VV(dst, dst, tmp, VECTOR_UNMASKED); \ + break; \ + } \ + } while (0) + + SHA1_F(qD, qB, qC, q0, qT); + VROR_VI(qB, qB, 2, VECTOR_UNMASKED); + SHA1_F(qU, qA, qB, qC, qT); + VROR_VI(qT, qA, 2, VECTOR_UNMASKED); + VADD_VV(qU, qU, q0, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q0, qM, 3, VECTOR_UNMASKED); + VADD_VV(qD, qD, q0, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q0, qM, 2, VECTOR_UNMASKED); + VADD_VV(qU, qU, q0, VECTOR_UNMASKED); + VROR_VI(qA, qA, 27, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q0, qM, 1, VECTOR_UNMASKED); + VADD_VV(qC, qC, q0, VECTOR_UNMASKED); + VADD_VV(qA, qA, qD, VECTOR_UNMASKED); + + VROR_VI(qD, qA, 27, VECTOR_UNMASKED); + VADD_VV(qD, qD, qU, VECTOR_UNMASKED); + SHA1_F(qU, qA, qT, qB, q0); + VADD_VV(qU, qU, qC, VECTOR_UNMASKED); + VADD_VV(qB, qB, qM, VECTOR_UNMASKED); + + VROR_VI(qA, qA, 2, VECTOR_UNMASKED); + VROR_VI(qM, qD, 2, VECTOR_UNMASKED); + SHA1_F(qC, qD, qA, qT, q0); + VROR_VI(q0, qD, 27, VECTOR_UNMASKED); + VADD_VV(qC, qC, qB, VECTOR_UNMASKED); + VADD_VV(q0, q0, qU, VECTOR_UNMASKED); + VROR_VI(qD, q0, 27, VECTOR_UNMASKED); + VADD_VV(qD, qD, qC, VECTOR_UNMASKED); + +#undef SHA1_F + + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VMV_X_S(x7, qA); + VMV_X_S(x6, qM); + VMV_X_S(x5, q0); + VMV_X_S(x4, qD); + VMV_S_X(qT, x4); + VSLIDE1UP_VX(v0, qT, x5, VECTOR_UNMASKED); + VSLIDE1UP_VX(qT, v0, x6, VECTOR_UNMASKED); + VSLIDE1UP_VX(v0, qT, x7, VECTOR_UNMASKED); break; + } default: DEFAULT; } @@ -1073,15 +1181,16 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETFLAGS; \ } \ nextop = F8; \ - GETGD; \ + GETGDsd; \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ if (dyn->insts[ninst].nat_flags_fusion) { \ NATIVEMV(NATYES, gd, ed); \ } else { \ MV##YES(gd, ed, tmp1); \ } \ - if (!rex.w) ZEROUP(gd); \ + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); \ } else { \ addr = geted(dyn, addr, ninst, nextop, &ed, tmp2, tmp3, &fixedaddress, rex, NULL, 1, 0); \ if (dyn->insts[ninst].nat_flags_fusion) { \ @@ -1090,7 +1199,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni B##NO(tmp1, 8); \ } \ LDxw(gd, ed, fixedaddress); \ - if (!rex.w) ZEROUP(gd); \ + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); \ } GOCOND(0x40, "CMOV", "Gd, Ed"); @@ -1098,7 +1207,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x50: INST_NAME("MOVMSKPS Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEX(x1, 0, 12); XOR(gd, gd, gd); for (int i = 0; i < 4; ++i) { @@ -1143,7 +1252,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni s0 = fpu_get_scratch(dyn); s1 = fpu_get_scratch(dyn); // 1.0f v0 = fpu_get_scratch(dyn); // 0.0f - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(s1, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) { FCVTSW(v0, xZR, RD_DYN); @@ -1184,7 +1293,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEX(x2, 0, 12); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(d0, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) MOV32w(x6, 0x00400000); @@ -1457,12 +1566,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, gback, gdoffset + i * 4); - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - BEQZ(x3, 12); - FLES(x3, s1, s0); - BEQZ(x3, 8); + FLTS(x3, s0, s1); + BNEZ(x3, 8); FSW(s0, gback, gdoffset + i * 4); } break; @@ -1698,6 +1803,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGM(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -1927,11 +2033,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); if (rex.w) FMVXD(ed, v0); else { FMVXW(ed, v0); - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } } else { addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, 0); @@ -1961,7 +2068,6 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni j64 = (uint32_t)(addr + i32_); \ else \ j64 = addr + i32_; \ - BARRIER(BARRIER_MAYBE); \ JUMP(j64, 1); \ if (!dyn->insts[ninst].nat_flags_fusion) { \ GETFLAGS; \ @@ -2014,8 +2120,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni eb1 = TO_NAT(ed & 3); \ } \ if (eb2) { \ - LUI(tmp1, 0xffff0); \ - ORI(tmp1, tmp1, 0xff); \ + MOV64x(tmp1, 0xFFFFFFFFFFFF00FF); \ AND(eb1, eb1, tmp1); \ SLLI(tmp3, tmp3, 8); \ } else { \ @@ -2046,6 +2151,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0); @@ -2069,14 +2175,14 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("SHLD Ed, Gd, Ib"); if (geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 63 : 31)) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); GETGD; u8 = F8 & (rex.w ? 63 : 31); emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4, x5); WBACK; } else { FAKEED; - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } F8; } break; @@ -2089,8 +2195,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined GETGD; - GETED(0); - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + GETEDsd(0); + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x3, xZR); emit_shld32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); @@ -2104,6 +2210,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); wback = 0; } else { SMREAD(); @@ -2134,7 +2241,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 0xAC: @@ -2142,14 +2249,14 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("SHRD Ed, Gd, Ib"); if (geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 63 : 31)) { SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED(1); + GETEDsd(1); GETGD; u8 = F8 & (rex.w ? 63 : 31); emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4, x5); WBACK; } else { FAKEED; - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } F8; } break; @@ -2162,8 +2269,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); GETGD; - GETED(0); - if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); } + GETEDsd(0); + if (!rex.w && MODREG) { if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f); BEQ_NEXT(x3, xZR); emit_shrd32(dyn, ninst, rex, ed, gd, x3, x5, x4, x6); @@ -2194,7 +2301,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("FXSAVE Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); SKIPTEST(x1); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0); CALL(rex.is32bits ? (const_fpu_fxsave32) : (const_fpu_fxsave64), -1, ed, 0); break; @@ -2202,7 +2309,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("FXRSTOR Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); SKIPTEST(x1); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0); CALL(rex.is32bits ? (const_fpu_fxrstor32) : (const_fpu_fxrstor64), -1, ed, 0); break; @@ -2267,7 +2374,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni OR(x4, x4, x5); // x4 = x4 | (x3 & 0b10000) >> 4; SRLIW(x5, x3, 4); - ANDI(x5, x5, 2); + ANDI(x5, x5, 1); OR(x4, x4, x5); } SW(x4, wback, fixedaddress); @@ -2275,7 +2382,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 4: INST_NAME("XSAVE Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, rex.is32bits); CALL(const_fpu_xsave, -1, ed, x2); @@ -2283,7 +2390,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 5: INST_NAME("XRSTOR Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, rex.is32bits); CALL(const_fpu_xrstor, -1, ed, x2); @@ -2307,7 +2414,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("IMUL Gd, Ed"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); CLEAR_FLAGS(); if (rex.w) { @@ -2349,7 +2456,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ZEXTW2(gd, x5); } else { MULxw(gd, gd, ed); - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } } IFX (X_SF) { @@ -2382,10 +2489,13 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("CMPXCHG Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); nextop = F8; - GETGD; + GETGDs; + MARKREGsd(xRAX); MVxw(x7, xRAX); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); + UP32_READ(ed); MVxw(x1, ed); wback = 0; } else { @@ -2414,6 +2524,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); wback = 0; } else { SMREAD(); @@ -2445,13 +2556,13 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 0xB6: INST_NAME("MOVZX Gd, Eb"); nextop = F8; - GETGD; + GETGDd; SCRATCH_USAGE(0); if (MODREG) { if (rex.rex) { @@ -2477,7 +2588,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xB7: INST_NAME("MOVZX Gd, Ew"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); ZEXTH(gd, ed); @@ -2505,7 +2616,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("BTS Ed, Ib"); SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); - GETED(1); + GETEDsd(1); u8 = F8; u8 &= (rex.w ? 0x3f : 0x1f); if (cpuext.zbs) { @@ -2534,13 +2645,13 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE(); } MARK; - if (!rex.w && !wback) ZEROUP(ed); + if (!rex.w && !wback) if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); break; case 6: INST_NAME("BTR Ed, Ib"); SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); - GETED(1); + GETEDsd(1); u8 = F8; u8 &= (rex.w ? 0x3f : 0x1f); if (cpuext.zbs) { @@ -2569,14 +2680,14 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 7: INST_NAME("BTC Ed, Ib"); SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); - GETED(1); + GETEDsd(1); u8 = F8; u8 &= rex.w ? 0x3f : 0x1f; BEXTI(x3, ed, u8); // F_CF is 1 @@ -2594,7 +2705,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; default: @@ -2609,6 +2720,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGsd(ed); wback = 0; } else { SMREAD(); @@ -2639,7 +2751,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SDxw(ed, wback, fixedaddress); SMWRITE(); } else if (!rex.w) { - ZEROUP(ed); + if (NEED_ZEROUP(ed)) ZEROUP_RESULT(ed); } break; case 0xBC: @@ -2711,7 +2823,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xBE: INST_NAME("MOVSX Gd, Eb"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { if (rex.rex) { wback = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -2729,12 +2841,12 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LB(gd, ed, fixedaddress); } if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); break; case 0xBF: INST_NAME("MOVSX Gd, Ew"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); SEXTH(gd, ed); @@ -2744,7 +2856,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LH(gd, ed, fixedaddress); } if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); break; case 0xC0: INST_NAME("XADD Eb, Gb"); @@ -2765,7 +2877,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("XADD Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); nextop = F8; - GETGD; + GETGDsd; GETED(0); if (ed != gd) MV(x7, ed); @@ -2835,7 +2947,9 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni nextop = F8; GETGD; if (MODREG) { - MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd); + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); + MVxw(ed, gd); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); SDxw(gd, ed, fixedaddress); @@ -2860,7 +2974,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xC5: INST_NAME("PEXTRW Gd,Em,Ib"); nextop = F8; - GETGD; + GETGDd; GETEM(x2, 1, 6); u8 = (F8) & 3; LHU(gd, wback, fixedaddress + u8 * 2); @@ -2900,6 +3014,10 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 1: if (rex.w) { INST_NAME("CMPXCHG16B Gq, Eq"); + MARKREGsd(xRAX); + MARKREGsd(xRDX); + MARKREGs(xRBX); + MARKREGs(xRCX); SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); SMREAD(); @@ -2961,6 +3079,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xCF: INST_NAME("BSWAP Reg"); gd = TO_NAT((opcode & 7) + (rex.b << 3)); + MARKREGsd(gd); REV8xw(gd, gd, x1, x2, x3, x4); break; case 0xD1: @@ -3032,7 +3151,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xD7: INST_NAME("PMOVMSKB Gd, Em"); nextop = F8; - GETGD; + GETGDd; GETEM(x2, 0, 1); LD(x1, wback, fixedaddress + 0); for (int i = 0; i < 8; i++) { @@ -3546,6 +3665,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xF7: INST_NAME("MASKMOVQ Gm, Em"); + UP32_READ(xRDI); nextop = F8; GETGM(); GETEM(x5, 0, 7); diff --git a/src/dynarec/rv64/dynarec_rv64_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_0f_vector.c index 0e61732d0..718e4e82e 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_0f_vector.c @@ -121,15 +121,15 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, } break; case 0x13: - INST_NAME("MOVLPS Ex, Gx"); nextop = F8; - GETG; - SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - v0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW64); if (MODREG) { - DEFAULT; - return addr; + INST_NAME("Illegal 0F 13"); + UDF(); } else { + INST_NAME("MOVLPS Ex, Gx"); + GETG; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); + v0 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, VECTOR_SEW64); VMV_X_S(x4, v0); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0); SD(x4, ed, fixedaddress); @@ -152,7 +152,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, // Zvbb VWSLL would help here.... VWADDU_VX(v0, q0, xZR, VECTOR_UNMASKED); VWADDU_VX(v1, q1, xZR, VECTOR_UNMASKED); - VSLIDE1UP_VX(d0, v1, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(d0, v1, xZR, VECTOR_UNMASKED); VOR_VV(q0, v0, d0, VECTOR_UNMASKED); break; case 0x15: @@ -180,7 +180,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, // Zvbb VWSLL would help here.... VWADDU_VX(v0, q0, xZR, VECTOR_UNMASKED); VWADDU_VX(v1, q1, xZR, VECTOR_UNMASKED); - VSLIDE1UP_VX(d0, v1 + 1, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(d0, v1 + 1, xZR, VECTOR_UNMASKED); VOR_VV(q0, v0 + 1, d0, VECTOR_UNMASKED); } break; @@ -196,7 +196,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VSLIDEUP_VI(v0, v1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 1, VECTOR_UNMASKED); } else { INST_NAME("MOVHPS Gx, Ex"); SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); @@ -206,27 +206,19 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); VECTOR_LOAD_VMASK(0xFF, x4, 1); VLE8_V(v1, ed, VECTOR_MASKED, VECTOR_NFIELD1); - VSLIDEUP_VI(v0, v1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 8, VECTOR_UNMASKED); } break; case 0x17: - INST_NAME("MOVHPS Ex, Gx"); nextop = F8; - SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - GETGX_vector(v0, 0, VECTOR_SEW64); - // EX->q[0] = GX->q[1]; if (MODREG) { - v1 = sse_get_reg_vector(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1, VECTOR_SEW64); - q0 = fpu_get_scratch(dyn); - VSLIDE1DOWN_VX(q0, v0, xZR, VECTOR_UNMASKED); - if (cpuext.xtheadvector) { - VECTOR_LOAD_VMASK(0b01, x4, 1); - VMERGE_VVM(v1, v1, q0); // implies VMASK - } else { - VMV_X_S(x4, q0); - VMV_S_X(v1, x4); - } + INST_NAME("Illegal 0F 17"); + UDF(); } else { + INST_NAME("MOVHPS Ex, Gx"); + SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); + GETGX_vector(v0, 0, VECTOR_SEW64); + // EX->q[0] = GX->q[1]; addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); q0 = fpu_get_scratch(dyn); VSLIDE1DOWN_VX(q0, v0, xZR, VECTOR_UNMASKED); @@ -282,6 +274,28 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SMWRITE2(); } break; + case 0x2C: + if (!BOX64ENV(dynarec_fastround)) return 0; + INST_NAME("CVTTPS2PI Gm, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETG; + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + v1 = sse_get_reg_vector(dyn, ninst, x1, ed, 0, VECTOR_SEW32); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + v1 = fpu_get_scratch(dyn); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); + LD(x4, ed, fixedaddress); + VMV_S_X(v1, x4); + } + v0 = mmx_get_reg_empty_vector(dyn, ninst, x1, x2, x3, gd); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 0.5); + VFCVT_RTZ_X_F_V(v0, v1, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + break; case 0x2E: case 0x2F: return 0; @@ -299,7 +313,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); ADDI(x4, xZR, 0b000010000111); VAND_VX(v0, q1, x4, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! + VRGATHER_VV_SAFE(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! VMV_V_V(q0, v1); break; case 0x01: @@ -314,7 +328,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VADD_VV(q0, d1, d0, VECTOR_UNMASKED); @@ -331,7 +345,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); @@ -349,7 +363,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSADD_VV(q0, d1, d0, VECTOR_UNMASKED); @@ -382,7 +396,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSUB_VV(q0, d0, d1, VECTOR_UNMASKED); @@ -399,7 +413,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); @@ -417,7 +431,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSSUB_VV(q0, d0, d1, VECTOR_UNMASKED); @@ -485,7 +499,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("MOVMSKPS Gd, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); - GETGD; + GETGDd; GETEX_vector(q0, 0, 0, VECTOR_SEW32); if (cpuext.xtheadvector) { v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL8); @@ -509,13 +523,26 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, } break; case 0x51: - if (!BOX64ENV(dynarec_fastround) || !BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("SQRTPS Gx, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); GETEX_vector(v0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v1); - VFSQRT_V(v1, v0, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastnan)) { + v2 = fpu_get_scratch(dyn); + q0 = fpu_get_scratch(dyn); + MOV32w(x4, 0x00400000); + VMV_V_X(v2, x4); + VOR_VV(v2, v0, v2, VECTOR_UNMASKED); + MOV32w(x4, 0xFFC00000); + VMV_V_X(q0, x4); + VMFEQ_VV(VMASK, v0, v0, VECTOR_UNMASKED); + VMERGE_VVM(v2, v2, q0); + VFSQRT_V(v1, v0, VECTOR_UNMASKED); + VMFNE_VV(VMASK, v1, v1, VECTOR_UNMASKED); + VMERGE_VVM(v1, v1, v2); + } else + VFSQRT_V(v1, v0, VECTOR_UNMASKED); break; case 0x52: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -525,7 +552,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETEX_vector(v0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v1); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); // 1.0f broadcast VFSQRT_V(v1, v0, VECTOR_UNMASKED); VFDIV_VV(v1, v2, v1, VECTOR_UNMASKED); // 1.0/sqrt(x) @@ -538,7 +565,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETEX_vector(v0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v1); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); // 1.0f broadcast VFDIV_VV(v1, v2, v0, VECTOR_UNMASKED); // 1.0/x break; @@ -632,7 +659,9 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); GETEX_vector(q0, 0, 0, VECTOR_SEW32); GETGX_empty_vector(v0); + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x6, x4); VFCVT_F_X_V(v0, q0, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); break; case 0x5C: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -650,8 +679,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX_vector(q0, 1, VECTOR_SEW32); GETEX_vector(q1, 0, 0, VECTOR_SEW32); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -669,8 +697,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX_vector(q0, 1, VECTOR_SEW32); GETEX_vector(q1, 0, 0, VECTOR_SEW32); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x60: INST_NAME("PUNPCKLBW Gm, Em"); @@ -727,7 +754,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, v0); - VSLIDEUP_VI(d0, v1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, v1, 4, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); VNCLIP_WI(v0, d0, 0, VECTOR_UNMASKED); break; @@ -761,10 +788,10 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); if (q0 == q1) { VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); } else { - VSLIDEUP_VI(q0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(q0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! VMAX_VX(d0, q0, xZR, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); @@ -834,7 +861,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, v0); - VSLIDEUP_VI(d0, v1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, v1, 2, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); VNCLIP_WI(v0, d0, 0, VECTOR_UNMASKED); break; @@ -1107,7 +1134,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0xC5: INST_NAME("PEXTRW Gd, Em, Ib"); nextop = F8; - GETGD; + GETGDd; if (MODREG) { SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); GETEM_vector(q0, 1); @@ -1131,7 +1158,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX_vector(v0, 1, VECTOR_SEW32); GETEX_vector(v1, 0, 1, VECTOR_SEW32); u8 = F8; - q0 = fpu_get_scratch(dyn); + q0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL1); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); if (cpuext.xtheadvector) { // lack of vrgatherei16.vv @@ -1146,8 +1173,8 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, q1 = q0; } vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); - VRGATHER_VV(d0, v0, q0, VECTOR_UNMASKED); - VRGATHER_VV(d1, v1, q1, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(d0, v0, q0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(d1, v1, q1, VECTOR_UNMASKED); } else { tmp64u0 = ((((uint64_t)u8 >> 2) & 3) << 16) | (u8 & 3); VECTOR_SPLAT_IMM(q0, tmp64u0, x4); @@ -1159,7 +1186,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, VRGATHEREI16_VV(d1, v1, q0, VECTOR_UNMASKED); } VMV_V_V(v0, d0); - VSLIDEUP_VI(v0, d1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, d1, 2, VECTOR_UNMASKED); break; case 0xD1: case 0xD2: @@ -1215,7 +1242,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0xD7: INST_NAME("PMOVMSKB Gd, Em"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); GETEM_vector(q0, 0); SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index d56e19006..ee735d404 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -687,7 +687,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni BNEZ_MARK(x3); ANDI(x3, ed, 0b10); - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); ZEXTH(x6, gd); BNEZ_MARK3(x3); @@ -850,7 +850,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); POP1_16(x1); FLAGS_ADJUST_FROM11(x1, x1, x2); - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(xFlags, xFlags, x2); OR(xFlags, xFlags, x1); MOV32w(x1, 0x3F7FF7); @@ -905,8 +905,11 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xA4: return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); case 0xA5: + UP32_READ(xRSI); + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP MOVSW"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRSI); @@ -952,13 +955,17 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE(); break; case 0xA7: + UP32_READ(xRSI); + UP32_READ(xRDI); switch (rex.rep) { case 1: case 2: if (rex.rep == 1) { INST_NAME("REPNZ CMPSW"); + UP32_READ(xRCX); } else { INST_NAME("REPZ CMPSW"); + UP32_READ(xRCX); } if (BOX64DRENV(dynarec_safeflags) > 1) { READFLAGS(X_ALL); @@ -1025,8 +1032,10 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_test16(dyn, ninst, x1, x2, x3, x4, x5); break; case 0xAB: + UP32_READ(xRDI); if (rex.rep) { INST_NAME("REP STOSW"); + UP32_READ(xRCX); CBZ_NEXT(xRCX); if (rex.is67 && !rex.is32bits) { ZEROUP(xRDI); @@ -1056,6 +1065,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xAD: + UP32_READ(xRSI); if (rex.rep) { DEFAULT; } else { @@ -1070,13 +1080,17 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xAF: + UP32_READ(xRDI); + if (rex.w) MARKREGs(xRAX); switch (rex.rep) { case 1: case 2: if (rex.rep == 1) { INST_NAME("REPNZ SCASW"); + UP32_READ(xRCX); } else { INST_NAME("REPZ SCASW"); + UP32_READ(xRCX); } if (BOX64DRENV(dynarec_safeflags) > 1) { READFLAGS(X_ALL); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 8a7c8742e..87cb99f65 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -209,6 +209,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } @@ -232,6 +233,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARKi(x5, xZR, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x1, 0x80000000); MARKi(i); } @@ -302,7 +304,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ed = x4; \ } \ B##NO(x1, 4 + 3 * 4); \ - LUI(x3, 0xffff0); \ + MOV64x(x3, 0xFFFFFFFFFFFF0000); \ AND(gd, gd, x3); \ OR(gd, gd, ed); @@ -464,7 +466,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SRLI(x3, x3, 29); MOV32w(x5, 0x007fffff); AND(x3, x3, x5); - LUI(x5, 0x7fc00); + MOV32w(x5, 0x7FC00000); OR(x3, x3, x5); OR(x3, x3, x4); FMVWX(d0, x3); @@ -488,7 +490,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FCVTLS(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 4 * i); } x87_restoreround(dyn, ninst, u8); @@ -534,10 +536,6 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int for (int i = 0; i < 2; ++i) { FLD(d0, gback, gdoffset + 8 * i); FLD(d1, wback, fixedaddress + 8 * i); - FEQD(x3, d0, d0); - FEQD(x4, d1, d1); - AND(x3, x3, x4); - BEQ(x3, xZR, 12); FLTD(x3, d0, d1); BNE(x3, xZR, 8); // continue FSD(d1, gback, gdoffset + 8 * i); @@ -584,12 +582,8 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int for (int i = 0; i < 2; ++i) { FLD(d0, gback, gdoffset + 8 * i); FLD(d1, wback, fixedaddress + 8 * i); - FEQD(x3, d0, d0); - FEQD(x4, d1, d1); - AND(x3, x3, x4); - BEQ(x3, xZR, 12); - FLED(x3, d0, d1); - BEQ(x3, xZR, 8); // continue + FLTD(x3, d1, d0); + BNE(x3, xZR, 8); // continue FSD(d1, gback, gdoffset + 8 * i); } break; @@ -770,7 +764,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SB(x3, gback, gdoffset + 2 * i + 1); } } else { - GETEX(x2, 0, 7); + GETEX(x2, 0, 15); for (int i = 0; i < 8; ++i) { // GX->ub[2 * i + 1] = EX->ub[i + 8]; LBU(x3, wback, fixedaddress + i + 8); @@ -1281,6 +1275,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (rex.w) { if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); LD(ed, gback, gdoffset + 0); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); @@ -1291,6 +1286,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); LWU(ed, gback, gdoffset + 0); } else { addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); @@ -1584,7 +1580,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); LBU(x1, ed, fixedaddress); } - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); AND(gd, gd, x5); OR(gd, gd, x1); break; @@ -1846,7 +1842,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); LB(x1, ed, fixedaddress); } - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); AND(gd, gd, x5); ANDN(x1, x1, x5, x5); OR(gd, gd, x1); @@ -1942,7 +1938,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xC5: INST_NAME("PEXTRW Gd,Ex,Ib"); nextop = F8; - GETGD; + GETGDd; GETEX(x1, 0, 14); u8 = (F8) & 7; LHU(gd, wback, fixedaddress + u8 * 2); @@ -2105,10 +2101,10 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("PMOVMSKB Gd, Ex"); nextop = F8; GETEX(x2, 0, 8); - GETGD; + GETGDd; LD(x1, wback, fixedaddress + 8); // high part LD(x2, wback, fixedaddress + 0); // low part, also destroyed wback(x2) - MOV64x(x5, 0x8080808080808080); + MOV64xs(x5, 0x8080808080808080, x3); MOV64x(x6, 0x0002040810204081); AND(x2, x2, x5); MUL(x2, x2, x6); @@ -2343,6 +2339,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQ_MARK(x5, xZR); + emit_mxcsr_raise_invalid(x5); MOV32w(x3, 0x80000000); MARK; FSFLAGSI(0); // // reset all bits @@ -2660,6 +2657,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xF7: INST_NAME("MASKMOVDQU Gx, Ex"); + UP32_READ(xRDI); nextop = F8; GETEX(x1, 0, 15); GETGX(); diff --git a/src/dynarec/rv64/dynarec_rv64_660f38.c b/src/dynarec/rv64/dynarec_rv64_660f38.c index 43caafdf9..b0830d564 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f38.c +++ b/src/dynarec/rv64/dynarec_rv64_660f38.c @@ -144,9 +144,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, INST_NAME("PHADDSW Gx, Ex"); nextop = F8; GETGX(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 4; ++i) { // tmp32s = GX->sw[i*2+0]+GX->sw[i*2+1]; // GX->sw[i] = sat(tmp32s); @@ -178,9 +177,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, nextop = F8; GETGX(); GETEX(x2, 0, 15); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LBU(x3, gback, gdoffset + i * 2); LB(x4, wback, fixedaddress + i * 2); @@ -255,9 +253,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, INST_NAME("PHSUBSW Gx, Ex"); nextop = F8; GETGX(); - LUI(x6, 0xFFFF8); - LUI(x7, 0x8); - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 4; ++i) { LH(x3, gback, gdoffset + 2 * (i * 2 + 0)); LH(x4, gback, gdoffset + 2 * (i * 2 + 1)); @@ -536,8 +533,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, nextop = F8; GETGX(); GETEX(x2, 0, 12); - LUI(x5, 0x10); // 65536 - ADDIW(x5, x5, -1); + MOV32w(x5, 0xFFFF); for (int i = 0; i < 4; ++i) { LW(x3, gback, gdoffset + i * 4); SATUw(x3, x5); @@ -968,7 +964,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, SRLI(x1, x1, 8); OR(x1, x1, x2); } - LUI(x2, 0xffff0); + MOV64x(x2, 0xFFFFFFFFFFFF0000); AND(gd, gd, x2); OR(gd, gd, x1); break; @@ -1081,16 +1077,16 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, // i = 0 FLD(d0, wback, fixedaddress); FEQD(x4, d0, d0); - BNEZ(x4, BOX64ENV(dynarec_fastnan) ? 8 : (7 * 4)); + BNEZ_MARK3(x4); if (!BOX64ENV(dynarec_fastnan)) { // sNaN -> qNaN, d0 |= (0x1 << 51) FMVXD(x3, d0); - ADDI(x4, xZR, 1); - SLLI(x4, x4, 51); + MOV64x(x4, 1ULL << 51); OR(x3, x3, x4); FMVDX(d0, x3); } B_MARK_nocond; + MARK3; // d0 is not nan FABSD(v1, d0); FLTD(x4, v1, d1); @@ -1118,16 +1114,16 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, // i = 1 FLD(d0, wback, fixedaddress + 8); FEQD(x4, d0, d0); - BNEZ(x4, BOX64ENV(dynarec_fastnan) ? 8 : (7 * 4)); + BNEZ_MARK4(x4); if (!BOX64ENV(dynarec_fastnan)) { // sNaN -> qNaN, d0 |= (0x1 << 51) FMVXD(x3, d0); - ADDI(x4, xZR, 1); - SLLI(x4, x4, 51); + MOV64x(x4, 1ULL << 51); OR(x3, x3, x4); FMVDX(d0, x3); } B_MARK2_nocond; + MARK4; // d0 is not nan FABSD(v1, d0); @@ -1370,6 +1366,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1388,6 +1385,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1410,6 +1408,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1431,6 +1430,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, GETGX(); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); + UP32_WRITE32(ed); wback = 0; } else { addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); @@ -1640,6 +1640,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, break; case 0x61: INST_NAME("PCMPESTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); nextop = F8; GETG; SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); @@ -1726,6 +1728,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, break; case 0x63: INST_NAME("PCMPISTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); nextop = F8; GETG; diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index 85480959c..889509c69 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -38,6 +38,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i int64_t fixedaddress, gdoffset; uint32_t vtypei; int unscaled; + int u8s; MAYUSE(d0); MAYUSE(d1); MAYUSE(q0); @@ -46,6 +47,8 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i MAYUSE(eb1); MAYUSE(eb2); MAYUSE(j64); + MAYUSE(u8s); + static const int8_t round_round[] = { RD_RNE, RD_RDN, RD_RUP, RD_RTZ }; switch (opcode) { case 0x10: INST_NAME("MOVUPD Gx, Ex"); @@ -131,7 +134,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VSLIDEUP_VI(v0, v1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 1, VECTOR_UNMASKED); } else { q0 = fpu_get_scratch(dyn); VXOR_VV(q0, q0, q0, VECTOR_UNMASKED); @@ -184,7 +187,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LD(x4, ed, fixedaddress); d0 = fpu_get_scratch(dyn); VMV_S_X(d0, x4); - VSLIDEUP_VI(v0, d0, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, d0, 1, VECTOR_UNMASKED); break; case 0x17: INST_NAME("MOVHPD Eq, Gx"); @@ -277,7 +280,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v1 = fpu_get_scratch(dyn); ADDI(x4, xZR, 0b000010001111); VAND_VX(v0, q1, x4, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! + VRGATHER_VV_SAFE(v1, q0, v0, VECTOR_UNMASKED); // registers cannot be overlapped!! VMV_V_V(q0, v1); break; case 0x01: @@ -292,7 +295,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); @@ -310,7 +313,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); @@ -329,7 +332,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); @@ -362,12 +365,49 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); VSUB_VV(q0, d0, d1, VECTOR_UNMASKED); break; + case 0x06: + INST_NAME("PHSUBD Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETGX_vector(q0, 1, VECTOR_SEW32); + GETEX_vector(q1, 0, 0, VECTOR_SEW32); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMV_V_V(v0, q0); + if (q1 & 1) VMV_V_V(d1, q1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); + ADDI(x4, xZR, 32); + VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); + VSUB_VV(q0, d0, d1, VECTOR_UNMASKED); + break; + case 0x07: + INST_NAME("PHSUBSW Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); + GETGX_vector(q0, 1, VECTOR_SEW16); + GETEX_vector(q1, 0, 0, VECTOR_SEW16); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMV_V_V(v0, q0); + if (q1 & 1) VMV_V_V(d1, q1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 8, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VNSRL_WI(d0, v0, 0, VECTOR_UNMASKED); + VNSRL_WI(d1, v0, 16, VECTOR_UNMASKED); + VSSUB_VV(q0, d0, d1, VECTOR_UNMASKED); + break; case 0x08 ... 0x0A: if (nextop == 0x08) { INST_NAME("PSIGNB Gx, Ex"); @@ -671,7 +711,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMUL_VV(d0, v0, v1, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - VSLIDEUP_VI(d0, d0 + 1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d0 + 1, 1, VECTOR_UNMASKED); VMV_V_V(v0, d0); } break; @@ -701,7 +741,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (q0 != q1) VNCLIPU_WX(v0, d1, xZR, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); if (q0 == q1) VMV_V_V(v0, q0); - VSLIDEUP_VI(q0, v0, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q0, v0, 4, VECTOR_UNMASKED); break; case 0x30: INST_NAME("PMOVZXBW Gx, Ex"); @@ -865,6 +905,14 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VXOR_VV(q0, q0, q0, VECTOR_UNMASKED); VMERGE_VIM(q0, q0, 0b11111); // implies vmask and widened it break; + case 0x38: + INST_NAME("PMINSB Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, VECTOR_SEW8); + GETEX_vector(q1, 0, 0, VECTOR_SEW8); + VMIN_VV(q0, q1, q0, VECTOR_UNMASKED); + break; case 0x39: INST_NAME("PMINSD Gx, Ex"); nextop = F8; @@ -889,6 +937,14 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW32); VMINU_VV(q0, q1, q0, VECTOR_UNMASKED); break; + case 0x3C: + INST_NAME("PMAXSB Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, VECTOR_SEW8); + GETEX_vector(q1, 0, 0, VECTOR_SEW8); + VMAX_VV(q0, q1, q0, VECTOR_UNMASKED); + break; case 0x3D: INST_NAME("PMAXSD Gx, Ex"); nextop = F8; @@ -897,6 +953,22 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETEX_vector(q1, 0, 0, VECTOR_SEW32); VMAX_VV(q0, q1, q0, VECTOR_UNMASKED); break; + case 0x3E: + INST_NAME("PMAXUW Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); + GETEX_vector(q1, 0, 0, VECTOR_SEW16); + GETGX_vector(q0, 1, VECTOR_SEW16); + VMAXU_VV(q0, q1, q0, VECTOR_UNMASKED); + break; + case 0x3F: + INST_NAME("PMAXUD Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETEX_vector(q1, 0, 0, VECTOR_SEW32); + GETGX_vector(q0, 1, VECTOR_SEW32); + VMAXU_VV(q0, q1, q0, VECTOR_UNMASKED); + break; case 0x40: INST_NAME("PMULLD Gx, Ex"); nextop = F8; @@ -905,6 +977,26 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW32); VMUL_VV(q0, q1, q0, VECTOR_UNMASKED); break; + case 0x41: + INST_NAME("PHMINPOSUW Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); + GETEX_vector(q0, 0, 0, VECTOR_SEW16); + GETGX_empty_vector(v0); + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + VMV_V_I(q2, -1); + VREDMINU_VS(q1, q0, q2, VECTOR_UNMASKED); + VMV_X_S(x4, q1); + ZEXTH(x4, x4); + VMSEQ_VX(VMASK, q0, x4, VECTOR_UNMASKED); + VFIRST_M(x5, VMASK, VECTOR_UNMASKED); + SLLI(x5, x5, 16); + OR(x4, x4, x5); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMV_S_X(v0, x4); + break; case 0xDB ... 0xDF: return 0; default: @@ -914,6 +1006,94 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x3A: // these are some more SSSE3+ opcodes opcode = F8; switch (opcode) { + case 0x08: { + INST_NAME("ROUNDPS Gx, Ex, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETEX_vector(q0, 0, 1, VECTOR_SEW32); + GETGX_empty_vector(v0); + u8 = F8; + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + int r3 = fpu_get_scratch(dyn); + if (u8 & 4) { + u8s = sse_setround(dyn, ninst, x5, x6); + } else { + ADDI(x5, xZR, round_round[u8 & 3]); + FSRM(x6, x5); + } + VFCVT_X_F_V(q1, q0, VECTOR_UNMASKED); // qi + VFCVT_F_X_V(q2, q1, VECTOR_UNMASKED); // qf + MOV32w(x5, 0x80000000); + VAND_VX(r3, q0, x5, VECTOR_UNMASKED); + VMSEQ_VI(VMASK, q1, 0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, r3); + MOV32w(x5, 0x00400000); + VOR_VX(r3, q0, x5, VECTOR_UNMASKED); + VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED); + VMERGE_VVM(q2, r3, q2); + d0 = fpu_get_scratch(dyn); + MOV32w(x5, 0x4f000000); + FMVWX(d0, x5); + VMFGE_VF(VMASK, q0, d0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + d1 = fpu_get_scratch(dyn); + MOV32w(x5, 0xcf000000); + FMVWX(d1, x5); + VMFLE_VF(VMASK, q0, d1, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + if (u8 & 4) { + x87_restoreround(dyn, ninst, u8s); + } else { + FSRM(x5, x6); + } + VMV_V_V(v0, q2); + break; + } + case 0x09: { + INST_NAME("ROUNDPD Gx, Ex, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); + GETEX_vector(q0, 0, 1, VECTOR_SEW64); + GETGX_empty_vector(v0); + u8 = F8; + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + int r3 = fpu_get_scratch(dyn); + if (u8 & 4) { + u8s = sse_setround(dyn, ninst, x5, x6); + } else { + ADDI(x5, xZR, round_round[u8 & 3]); + FSRM(x6, x5); + } + VFCVT_X_F_V(q1, q0, VECTOR_UNMASKED); // qi + VFCVT_F_X_V(q2, q1, VECTOR_UNMASKED); // qf + MOV64x(x5, 0x8000000000000000LL); + VAND_VX(r3, q0, x5, VECTOR_UNMASKED); + VMSEQ_VI(VMASK, q1, 0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, r3); + MOV64x(x5, 0x0008000000000000LL); + VOR_VX(r3, q0, x5, VECTOR_UNMASKED); + VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED); + VMERGE_VVM(q2, r3, q2); + d0 = fpu_get_scratch(dyn); + MOV64x(x5, 0x43e0000000000000LL); + FMVDX(d0, x5); + VMFGE_VF(VMASK, q0, d0, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + d1 = fpu_get_scratch(dyn); + MOV64x(x5, 0xc3e0000000000000LL); + FMVDX(d1, x5); + VMFLE_VF(VMASK, q0, d1, VECTOR_UNMASKED); + VMERGE_VVM(q2, q2, q0); + if (u8 & 4) { + x87_restoreround(dyn, ninst, u8s); + } else { + FSRM(x5, x6); + } + VMV_V_V(v0, q2); + break; + } case 0x0E: INST_NAME("PBLENDW Gx, Ex, Ib"); nextop = F8; @@ -949,7 +1129,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v0 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VSLIDEUP_VI(v0, q0, 16 - u8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q0, 16 - u8, VECTOR_UNMASKED); if (cpuext.vlen >= 32) { // clear high bits before slidedown! d0 = fpu_get_scratch(dyn); @@ -965,6 +1145,46 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (q0 != q1) VMV_V_V(q0, q1); } break; + case 0x42: + INST_NAME("MPSADBW Gx, Ex, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, VECTOR_SEW8); + GETEX_vector(q1, 0, 1, VECTOR_SEW8); + u8 = F8; + { + int m3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + int m4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + int m5 = fpu_borrow_reg(dyn, ninst, x1, x2, 9); + int m6 = fpu_borrow_reg(dyn, ninst, x1, x2, 10); + int m7 = fpu_borrow_reg(dyn, ninst, x1, x2, 11); + int m8 = fpu_borrow_reg(dyn, ninst, x1, x2, 12); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VMV_V_V(m7, q0); + VMV_V_V(m8, q1); + VID_V(m5, VECTOR_UNMASKED); + VSRL_VI(m6, m5, 3, VECTOR_UNMASKED); + VAND_VI(m5, m5, 7, VECTOR_UNMASKED); + VADD_VV(m5, m5, m6, VECTOR_UNMASKED); + int off5 = ((u8 >> 2) & 1) * 4; + int off6 = (u8 & 3) * 4; + if (off5) VADD_VI(m5, m5, off5, VECTOR_UNMASKED); + if (off6) VADD_VI(m6, m6, off6, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(m3, m7, m5, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(m4, m8, m6, VECTOR_UNMASKED); + VMAXU_VV(m7, m3, m4, VECTOR_UNMASKED); + VMINU_VV(m4, m3, m4, VECTOR_UNMASKED); + VSUB_VV(m7, m7, m4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 4); + VZEXT_VF2(m3, m7, VECTOR_UNMASKED); + VSLIDEDOWN_VI(m4, m3, 8, VECTOR_UNMASKED); + VADD_VV(m3, m3, m4, VECTOR_UNMASKED); + VSLIDEDOWN_VI(m4, m3, 16, VECTOR_UNMASKED); + VADD_VV(m3, m3, m4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VMV_V_V(q0, m3); + } + break; case 0x16: nextop = F8; if (rex.w) { @@ -1010,6 +1230,36 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SMWRITE2(); } break; + case 0x20: + INST_NAME("PINSRB Gx, Ed, Ib"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); + GETGX_vector(q0, 1, dyn->vector_eew); + if (MODREG) { + u8 = (F8) & 0xF; + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 1); + u8 = (F8) & 0xF; + LB(x4, ed, fixedaddress); + ed = x4; + } + if (cpuext.xtheadvector) { + VECTOR_LOAD_VMASK(1 << u8, x5, 1); + v0 = fpu_get_scratch(dyn); + VMERGE_VXM(v0, q0, ed); + VMV_V_V(q0, v0); + } else if (u8 == 0) { + VMV_S_X(q0, ed); + } else { + v0 = fpu_get_scratch(dyn); + VMV_S_X(v0, ed); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, (u8 + 1) / 16.0f); + VSLIDEUP_VI_SAFE(q0, v0, u8, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, 1); + } + break; case 0x22: INST_NAME("PINSRD Gx, Ed, Ib"); nextop = F8; @@ -1018,6 +1268,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (MODREG) { u8 = (F8) & (rex.w ? 1 : 3); ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 1); @@ -1025,12 +1276,29 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LDxw(x4, ed, fixedaddress); ed = x4; } - v0 = fpu_get_scratch(dyn); - VID_V(v0, VECTOR_UNMASKED); - VMSEQ_VI(VMASK, v0, u8, VECTOR_UNMASKED); - VMERGE_VXM(v0, q0, ed); - VMV_V_V(q0, v0); - sse_forget_reg_vector(dyn, ninst, x1, gd); + if (cpuext.xtheadvector) { + v0 = fpu_get_scratch(dyn); + if (rex.w) { + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + VECTOR_LOAD_VMASK(1 << (u8 * 2), x5, 1); + VMERGE_VXM(v0, q0, ed); + SRLI(x4, ed, 32); + VECTOR_LOAD_VMASK(1 << (u8 * 2 + 1), x5, 1); + VMERGE_VXM(q0, v0, x4); + } else { + VECTOR_LOAD_VMASK(1 << u8, x5, 1); + VMERGE_VXM(v0, q0, ed); + VMV_V_V(q0, v0); + } + } else if (u8 == 0) { + VMV_S_X(q0, ed); + } else { + v0 = fpu_get_scratch(dyn); + VMV_S_X(v0, ed); + vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, (u8 + 1) / (float)(rex.w ? 2 : 4)); + VSLIDEUP_VI_SAFE(q0, v0, u8, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, dyn->vector_sew, VECTOR_LMUL1, 1); + } break; case 0x40: INST_NAME("DPPS Gx, Ex, Ib"); @@ -1062,7 +1330,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("PMOVMSKD Gd, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - GETGD; + GETGDd; GETEX_vector(q0, 0, 0, VECTOR_SEW64); if (cpuext.xtheadvector) { v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); @@ -1204,8 +1472,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW64); GETEX_vector(q1, 0, 0, VECTOR_SEW64); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -1223,8 +1490,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETGX_vector(q0, 1, VECTOR_SEW64); GETEX_vector(q1, 0, 0, VECTOR_SEW64); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED); - VADD_VX(q0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(q0, q1, q0); break; case 0x60: INST_NAME("PUNPCKLBW Gx, Ex"); @@ -1279,13 +1545,13 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (cpuext.vlen >= 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); // double the vl for slideup. VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! } else { d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, q0); VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(d0, d1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d1, 8, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); VNCLIP_WI(q0, d0, 0, VECTOR_UNMASKED); @@ -1318,20 +1584,15 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); if (cpuext.vlen >= 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); // double the vl for slideup. - if (q0 == q1) { - VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! - VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); - } else { - VSLIDEUP_VI(q0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! - VMAX_VX(d0, q0, xZR, VECTOR_UNMASKED); - } + VMV_V_V(d0, q0); + VSLIDEUP_VI_SAFE(d0, q1, 8, VECTOR_UNMASKED); // splice q0 and q1 here! + VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); } else { d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, q0); VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 2); - VSLIDEUP_VI(d0, d1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d1, 8, VECTOR_UNMASKED); VMAX_VX(d0, d0, xZR, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); @@ -1386,13 +1647,13 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (cpuext.vlen >= 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 2); // double the vl for slideup. VMV_V_V(d0, q0); - VSLIDEUP_VI(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! + VSLIDEUP_VI_SAFE(d0, q1, 4, VECTOR_UNMASKED); // splice q0 and q1 here! } else { d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VMV_V_V(d0, q0); VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); - VSLIDEUP_VI(d0, d1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d1, 4, VECTOR_UNMASKED); } SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); VNCLIP_WI(q0, d0, 0, VECTOR_UNMASKED); @@ -1411,7 +1672,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VSLIDEUP_VI(v0, v1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 1, VECTOR_UNMASKED); } else { q0 = fpu_get_scratch(dyn); VXOR_VV(q0, q0, q0, VECTOR_UNMASKED); @@ -1484,7 +1745,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); GETEX_vector(q1, 0, 1, VECTOR_SEW64); GETGX_empty_vector(q0); - v0 = fpu_get_scratch(dyn); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL1); tmp64u0 = F8; if (cpuext.xtheadvector) { // lack of vrgatherei16.vv v1 = fpu_get_scratch(dyn); @@ -1500,24 +1761,24 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); // clears upper bits! } if (tmp64u0 == tmp64u1) { - VSLIDE1UP_VX(v0, v1, x4, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, x4, VECTOR_UNMASKED); } else if (tmp64u0 == 0) { - VSLIDE1UP_VX(v0, v1, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, xZR, VECTOR_UNMASKED); } else { MOV64x(x4, tmp64u0); - VSLIDE1UP_VX(v0, v1, x4, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, x4, VECTOR_UNMASKED); } } SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); if (q0 == q1) { - VRGATHER_VV(v1, q1, v0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q1, v0, VECTOR_UNMASKED); VMV_V_V(q0, v1); } else { - VRGATHER_VV(q0, q1, v0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(q0, q1, v0, VECTOR_UNMASKED); } } else { tmp64u0 = ((tmp64u0 >> 6) << 48) | (((tmp64u0 >> 4) & 3) << 32) | (((tmp64u0 >> 2) & 3) << 16) | (tmp64u0 & 3); - VECTOR_SPLAT_IMM(v0, tmp64u0, x4); + VECTOR_SPLAT_IMM_S(v0, tmp64u0, x4, x3); SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); if (q0 == q1) { v1 = fpu_get_scratch(dyn); @@ -1686,7 +1947,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i } else { d0 = fpu_get_scratch(dyn); VXOR_VV(d0, d0, d0, VECTOR_UNMASKED); - VSLIDEUP_VI(d0, q0, u8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, q0, u8, VECTOR_UNMASKED); if (MODREG) { VMV_V_V(q0, d0); } else { @@ -1727,8 +1988,8 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); - v0 = sse_get_reg_empty_vector(dyn, ninst, x1, ed); v1 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, dyn->vector_eew); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, ed); VMV_V_V(v0, v1); } else { v1 = sse_get_reg_vector(dyn, ninst, x1, gd, 0, dyn->vector_eew); @@ -1806,7 +2067,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("PEXTRW Gd, Ex, Ib"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW16, 1); - GETGD; + GETGDd; if (MODREG) { GETEX_vector(q0, 0, 1, VECTOR_SEW16); u8 = (F8) & 7; @@ -1849,7 +2110,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = v0; VMV_X_S(x4, d0); } - VSLIDE1UP_VX(v0, v1, x4, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(v0, v1, x4, VECTOR_UNMASKED); break; case 0xD1: case 0xD2: @@ -1923,7 +2184,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("PMOVMSKB Gd, Ex"); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); - GETGD; + GETGDd; GETEX_vector(q0, 0, 0, VECTOR_SEW8); if (cpuext.xtheadvector) { v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL8); @@ -2260,7 +2521,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMULU_VV(d0, v0, v1, VECTOR_UNMASKED); SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); - VSLIDEUP_VI(d0, d0 + 1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(d0, d0 + 1, 1, VECTOR_UNMASKED); VMV_V_V(v0, d0); } break; @@ -2300,7 +2561,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VSLIDEDOWN_VI(d0, v1, 8, VECTOR_UNMASKED); VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); VREDSUM_VS(v1, d0, v1, VECTOR_MASKED); // sum high 64 - VSLIDEUP_VI(v0, v1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, v1, 4, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 1); VMV_V_V(q0, v0); break; @@ -2343,6 +2604,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i break; case 0xF7: INST_NAME("MASKMOVDQU Gx, Ex"); + UP32_READ(xRDI); nextop = F8; SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); GETGX_vector(q0, 0, VECTOR_SEW8); diff --git a/src/dynarec/rv64/dynarec_rv64_66f0.c b/src/dynarec/rv64/dynarec_rv64_66f0.c index 0a913fa60..90fd7662d 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f0.c +++ b/src/dynarec/rv64/dynarec_rv64_66f0.c @@ -113,9 +113,8 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 &= 0x0f; ADDI(x3, wback, u8 >> 3); ANDI(x4, x3, 3); - SLLI(x4, x4, 3); ADDI(x5, xZR, u8 & 7); - ADD(x5, x4, x5); + ADDSL(x5, x5, x4, 3, x4); ANDI(x3, x3, ~3); ADDI(x6, xZR, 1); SLL(x6, x6, x5); @@ -143,9 +142,8 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 &= 0x0f; ADDI(x3, wback, u8 >> 3); ANDI(x4, x3, 3); - SLLI(x4, x4, 3); ADDI(x5, xZR, u8 & 7); - ADD(x5, x4, x5); + ADDSL(x5, x5, x4, 3, x4); ANDI(x3, x3, ~3); ADDI(x6, xZR, 1); SLL(x6, x6, x5); @@ -174,9 +172,8 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 &= 0x0f; ADDI(x3, wback, u8 >> 3); ANDI(x4, x3, 3); - SLLI(x4, x4, 3); ADDI(x5, xZR, u8 & 7); - ADD(x5, x4, x5); + ADDSL(x5, x5, x4, 3, x4); ANDI(x3, x3, ~3); ADDI(x6, xZR, 1); SLL(x6, x6, x5); diff --git a/src/dynarec/rv64/dynarec_rv64_66f20f.c b/src/dynarec/rv64/dynarec_rv64_66f20f.c index c7745db4d..c6bb88bfd 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_66f20f.c @@ -60,17 +60,29 @@ uintptr_t dynarec64_66F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GETGD; GETEW(x1, 0); MV(x5, ed); - ZEROUP(gd); - MOV32w(x2, 0x82f63b78); - for (int j = 0; j < 2; ++j) { - SRLI(x6, x5, 8 * j); - ANDI(x6, x6, 0xFF); - XOR(gd, gd, x6); - for (int i = 0; i < 8; i++) { - SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); - ANDI(x6, (i & 1) ? x4 : gd, 1); - BEQZ(x6, 4 + 4); - XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + if (cpuext.zbc) { + ZEROUP(gd); + XOR(x5, x5, gd); + SLLI(x5, x5, 48); + MOV64xs(x2, 0x4869EC38DEA713F1ULL, x3); + CLMUL(x5, x5, x2); + MOV64x(x2, 0x105EC76F1ULL); + CLMULH(x5, x5, x2); + SRLI(gd, gd, 16); + XOR(gd, x5, gd); + } else { + ZEROUP(gd); + MOV32w(x2, 0x82f63b78); + for (int j = 0; j < 2; ++j) { + SRLI(x6, x5, 8 * j); + ANDI(x6, x6, 0xFF); + XOR(gd, gd, x6); + for (int i = 0; i < 8; i++) { + SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); + ANDI(x6, (i & 1) ? x4 : gd, 1); + BEQZ(x6, 4 + 4); + XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + } } } break; diff --git a/src/dynarec/rv64/dynarec_rv64_66f30f.c b/src/dynarec/rv64/dynarec_rv64_66f30f.c index b9be7b9b2..4c3264542 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_66f30f.c @@ -51,6 +51,7 @@ uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in switch (opcode) { case 0xB8: + if (rex.w) return dynarec64_F30F(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); INST_NAME("POPCNT Gw, Ew"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); SET_DFNONE(); @@ -91,6 +92,7 @@ uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GWBACK; break; case 0xBC: + if (rex.w) return dynarec64_F30F(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); INST_NAME("TZCNT Gw, Ew"); if (!BOX64DRENV(dynarec_safeflags)) { SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); @@ -123,6 +125,7 @@ uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GWBACK; break; case 0xBD: + if (rex.w) return dynarec64_F30F(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); INST_NAME("LZCNT Gw, Ew"); if (!BOX64DRENV(dynarec_safeflags)) { SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); diff --git a/src/dynarec/rv64/dynarec_rv64_arch.c b/src/dynarec/rv64/dynarec_rv64_arch.c index 9e6c64cb0..409f673d6 100644 --- a/src/dynarec/rv64/dynarec_rv64_arch.c +++ b/src/dynarec/rv64/dynarec_rv64_arch.c @@ -26,31 +26,34 @@ typedef struct arch_flags_s { - uint8_t ignore:1; + uint8_t defered:1; // deferred flags are authoritative at this instruction } arch_flags_t; #define X87_ST_D 0 #define X87_ST_F 1 #define X87_ST_I64 2 -#define XMM0 0 -#define X870 XMM0 + 16 -#define EMM0 XMM0 + 16 + typedef struct arch_x87_s { - int8_t delta; //up to +/-7 + int8_t delta; // pending x87 stack count at that instruction uint8_t x87; // 1bit is STx present - uint16_t x87_type; // 2bits per STx type - uint32_t x87_pos; //4bits per STx position (well, 3 would be enough) + uint8_t reg[8]; // FP register of each present STx + uint8_t type[8]; // type of each present STx } arch_x87_t; typedef struct arch_mmx_s { uint8_t mmx; //1bit for each mmx reg present + uint8_t vector; // 1bit for each mmx reg cached in a vector register + uint8_t reg[8]; // register of each present mmx reg } arch_mmx_t; typedef struct arch_sse_s { - uint16_t sse; //1bit for each sse reg present + uint16_t sse; // 1bit for each sse reg present + uint16_t vector; // 1bit for each sse reg cached in a vector register + uint8_t reg[16]; // register of each present sse reg + uint8_t single[16]; // 1 if the sse value is single precision } arch_sse_t; typedef struct arch_ymm_s @@ -67,6 +70,8 @@ typedef struct arch_arch_s #undef GO uint16_t unaligned:1; uint16_t seq:10; // how many instruction on the same values + int16_t rsp; // pending rsp offset at the end of this instruction + uint16_t up32; // GPRs with pending 32-bit zero-up at the end of this instruction } arch_arch_t; typedef struct arch_build_s @@ -75,7 +80,9 @@ typedef struct arch_build_s SUPER() #undef GO uint8_t unaligned; - #define GO(A) arch_##A##_t A##_; + int16_t rsp; + uint16_t up32; +#define GO(A) arch_##A##_t A##_; SUPER() #undef GO } arch_build_t; @@ -83,10 +90,83 @@ typedef struct arch_build_s static int arch_build(dynarec_rv64_t* dyn, int ninst, arch_build_t* arch) { memset(arch, 0, sizeof(arch_build_t)); - // todo + flagcache_t f = dyn->insts[ninst].f_entry; + if (f == status_set || f == status_unk) { + arch->flags = 1; + arch->flags_.defered = 1; + } // opcode can handle unaligned arch->unaligned = dyn->insts[ninst].unaligned; - return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned; + arch->rsp = dyn->insts[ninst].rsp_entry; + arch->up32 = dyn->insts[ninst].up32_pending; + extcache_t* e = &dyn->insts[ninst].e; + for (int i = 0; i < 32; ++i) { + if (!e->extcache[i].t) + continue; + int reg = EXTREG(i); + switch (e->extcache[i].t) { + case EXT_CACHE_ST_D: + case EXT_CACHE_ST_F: + case EXT_CACHE_ST_I64: { + int st = e->extcache[i].n & 7; + arch->x87_.x87 |= (uint8_t)(1 << st); + arch->x87_.reg[st] = (uint8_t)reg; + arch->x87_.type[st] = (uint8_t)(e->extcache[i].t - EXT_CACHE_ST_D); + break; + } + case EXT_CACHE_MM: { + int mm = e->extcache[i].n & 7; + arch->mmx_.mmx |= (uint8_t)(1 << mm); + arch->mmx_.reg[mm] = (uint8_t)reg; + break; + } + case EXT_CACHE_MMV: { + int mm = e->extcache[i].n & 7; + arch->mmx_.mmx |= (uint8_t)(1 << mm); + arch->mmx_.vector |= (uint8_t)(1 << mm); + arch->mmx_.reg[mm] = (uint8_t)reg; + break; + } + case EXT_CACHE_SS: + case EXT_CACHE_SD: + case EXT_CACHE_XMMR: + case EXT_CACHE_XMMW: + case EXT_CACHE_YMMR: + case EXT_CACHE_YMMW: { + int xmm = e->extcache[i].n & 15; + arch->sse_.sse |= (uint16_t)(1 << xmm); + if (e->extcache[i].t == EXT_CACHE_XMMR || e->extcache[i].t == EXT_CACHE_XMMW + || e->extcache[i].t == EXT_CACHE_YMMR || e->extcache[i].t == EXT_CACHE_YMMW) + arch->sse_.vector |= (uint16_t)(1 << xmm); + arch->sse_.reg[xmm] = (uint8_t)reg; + arch->sse_.single[xmm] = (e->extcache[i].t == EXT_CACHE_SS) ? 1 : 0; + break; + } + default: + break; + } + } + // pending x87 stack count + if (e->x87stack) + arch->x87_.delta = e->x87stack; + for (int i = 0; i < 32; ++i) { + if (e->extcache[i].t != EXT_CACHE_XMMR && e->extcache[i].t != EXT_CACHE_XMMW + && e->extcache[i].t != EXT_CACHE_YMMR && e->extcache[i].t != EXT_CACHE_YMMW) + continue; + int xmm = e->extcache[i].n & 15; + if (e->ssecache[xmm].ymm) + arch->ymm_.ymm |= (uint16_t)(1 << xmm); + } + arch->ymm_.ymm0 = e->ymm0; + if (arch->ymm_.ymm || arch->ymm_.ymm0) + arch->ymm = 1; + if (arch->x87_.x87 || arch->x87_.delta) + arch->x87 = 1; + if (arch->mmx_.mmx) + arch->mmx = 1; + if (arch->sse_.sse) + arch->sse = 1; + return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned + (arch->up32 != 0) + (arch->rsp != 0); } size_t get_size_arch(dynarec_rv64_t* dyn) @@ -124,6 +204,8 @@ static void build_next(arch_arch_t* arch, arch_build_t* build) SUPER() #undef GO arch->unaligned = build->unaligned; + arch->rsp = build->rsp; + arch->up32 = build->up32; arch->seq = 0; void* p = ((void*)arch)+sizeof(arch_arch_t); #define GO(A) \ @@ -144,6 +226,78 @@ static int sizeof_arch(arch_arch_t* arch) return sz; } + +static int read_vector_reg(const void* vframe, size_t vlenb, int reg, void* buf, size_t sz) +{ + if (vframe) { + if (vlenb < sz) return 0; + memcpy(buf, (const uint8_t*)vframe + (reg & 31) * vlenb, sz); + return 1; + } + + // HACK: if vframe is absent, the live register is read instead. + switch (reg & 31) { +#define VREG_CASE(N) \ + case N: \ + __asm__ volatile(".option push\n\t.option arch, +v\n\tvsetvli t0, %1, 0\n\tvse8.v v" #N \ + ", (%0)\n\t.option pop\n\t" ::"r"(buf), \ + "r"(sz) \ + : "memory", "t0"); \ + return 1; + VREG_CASE(0) + VREG_CASE(1) + VREG_CASE(2) + VREG_CASE(3) + VREG_CASE(4) + VREG_CASE(5) + VREG_CASE(6) + VREG_CASE(7) + VREG_CASE(8) + VREG_CASE(9) + VREG_CASE(10) + VREG_CASE(11) + VREG_CASE(12) + VREG_CASE(13) + VREG_CASE(14) + VREG_CASE(15) + VREG_CASE(16) + VREG_CASE(17) + VREG_CASE(18) + VREG_CASE(19) + VREG_CASE(20) + VREG_CASE(21) + VREG_CASE(22) + VREG_CASE(23) + VREG_CASE(24) + VREG_CASE(25) + VREG_CASE(26) + VREG_CASE(27) + VREG_CASE(28) + VREG_CASE(29) + VREG_CASE(30) + VREG_CASE(31) +#undef VREG_CASE + } + return 0; +} + +static const void* get_vframe(const ucontext_t* p, size_t* vlenb) +{ + // struct __riscv_extra_ext_header { uint32_t padding[129]; uint32_t reserved; struct { uint32_t magic, size; } hdr; } + const uint8_t* fp = (const uint8_t*)&p->uc_mcontext.__fpregs; + if (*(const uint32_t*)(fp + 520) != 0x53465457) // RISCV_V_MAGIC + return NULL; + struct riscv_v_ext_state_s { + unsigned long vstart, vl, vtype, vcsr, vlenb; + void* datap; + }; + const struct riscv_v_ext_state_s* vs = (const struct riscv_v_ext_state_s*)(fp + 528); + if (!vs->datap || vs->vlenb < 16 || vs->vlenb > 4096) + return NULL; + *vlenb = vs->vlenb; + return vs->datap; +} + void* populate_arch(dynarec_rv64_t* dyn, void* p, size_t sz) { arch_build_t build = {0}; @@ -175,7 +329,7 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) return; int ninst = getX64AddressInst(db, x64pc); dynarec_log(LOG_INFO, "adjust_arch(...), db=%p, x64pc=%p, nints=%d", db, (void*)x64pc, ninst); - if(ninst<0) { + if(ninst<0 || ninst >= db->isize) { dynarec_log(LOG_INFO, "\n"); return; } @@ -184,28 +338,110 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc) CHECK_FLAGS(emu); return; } - // look for state at ninst-1 + // look for state at ninst. arch_arch_t* arch = db->arch; + // look for state at ninst-1. + arch_arch_t* prev_arch = arch; arch_arch_t* next = arch; #define GO(A) arch_##A##_t* A = NULL; SUPER() #undef GO - int i = 0; - while(iseq; dynarec_log(LOG_INFO, "[ seq=%d%s%s%s%s%s ] ", arch->seq, arch->flags?" Flags":"", arch->x87?" x87":"", arch->mmx?" MMX":"", arch->sse?" SSE":"", arch->ymm?" YMM":""); next = (arch_arch_t*)((uintptr_t)next + sizeof_arch(arch)); } int sz = sizeof(arch_arch_t); #define GO(A) \ - if(arch->A) { \ - A = (arch_##A##_t*)((uintptr_t)arch + sz); \ + if(prev_arch->A) { \ + A = (arch_##A##_t*)((uintptr_t)prev_arch + sz); \ sz+=sizeof(arch_##A##_t); \ } SUPER() #undef GO - // todo + flags = arch->flags ? (arch_flags_t*)((uintptr_t)arch + sizeof(arch_arch_t)) : NULL; + if (!flags || !flags->defered) emu->df = d_none; + uint16_t up32 = arch->up32; + while (up32) { + int r = __builtin_ctz(up32); + up32 &= up32 - 1; + emu->regs[r].q[0] &= 0xffffffffULL; + } + if (arch->rsp) { + dynarec_log(LOG_INFO, " rsp[%d] ", arch->rsp); + emu->regs[_SP].q[0] += arch->rsp; + } + if (sse || mmx || ymm) { + size_t vlenb = 0; + const void* vframe = get_vframe(p, &vlenb); + if (sse) { + dynarec_log(LOG_INFO, " sse[%x, vector=%x, %s] ", sse->sse, sse->vector, vframe ? "frame" : "live"); + for (int i = 0; i < 16; ++i) { + if (!((sse->sse >> i) & 1)) + continue; + if ((sse->vector >> i) & 1) { + uint8_t vbuf[32]; + if (read_vector_reg(vframe, vlenb, sse->reg[i], vbuf, 16)) + memcpy(&emu->xmm[i], vbuf, 16); + } else if (sse->single[i]) { + uint64_t raw = p->uc_mcontext.__fpregs.__d.__f[sse->reg[i] & 31]; + *(uint32_t*)&emu->xmm[i] = (uint32_t)raw; + } else { + emu->xmm[i].q[0] = p->uc_mcontext.__fpregs.__d.__f[sse->reg[i] & 31]; + } + } + } + if (ymm) { + dynarec_log(LOG_INFO, " ymm[%x, 0=%x] ", ymm->ymm, ymm->ymm0); + for (int i = 0; i < 16; ++i) { + if (((ymm->ymm >> i) & 1) && sse && ((sse->vector >> i) & 1)) { + uint8_t vbuf[32]; + if (read_vector_reg(vframe, vlenb, sse->reg[i], vbuf, 32)) + memcpy(&emu->ymm[i], vbuf + 16, 16); + } + if ((ymm->ymm0 >> i) & 1) + emu->ymm[i].q[0] = emu->ymm[i].q[1] = 0; + } + } + if (mmx) { + dynarec_log(LOG_INFO, " mmx[%x, vector=%x] ", mmx->mmx, mmx->vector); + for (int i = 0; i < 8; ++i) { + if (!((mmx->mmx >> i) & 1)) + continue; + if ((mmx->vector >> i) & 1) { + uint8_t vbuf[16]; + if (read_vector_reg(vframe, vlenb, mmx->reg[i], vbuf, 8)) + emu->mmx[i].q = *(uint64_t*)vbuf; + } else { + emu->mmx[i].q = p->uc_mcontext.__fpregs.__d.__f[mmx->reg[i] & 31]; + } + } + } + } + if (x87) { + dynarec_log(LOG_INFO, " x87[%x, delta=%d] ", x87->x87, x87->delta); + if (x87->delta) + emu->top = (emu->top - x87->delta) & 7; + for (int i = 0; i < 8; ++i) { + if (!((x87->x87 >> i) & 1)) + continue; + uint64_t raw = p->uc_mcontext.__fpregs.__d.__f[x87->reg[i] & 31]; + switch (x87->type[i]) { + case X87_ST_F: + emu->x87[(emu->top + i) & 7].d = *(float*)&raw; + break; + case X87_ST_I64: + emu->x87[(emu->top + i) & 7].d = (double)*(int64_t*)&raw; + break; + default: + emu->x87[(emu->top + i) & 7].d = *(double*)&raw; + break; + } + } + } dynarec_log(LOG_INFO, "\n"); } @@ -216,7 +452,7 @@ int arch_unaligned(dynablock_t* db, uintptr_t x64pc) if(!db->arch_size || !db->arch) return 0; int ninst = getX64AddressInst(db, x64pc); - if(ninst<0) { + if(ninst<0 || ninst >= db->isize) { return 0; } // look for state at ninst diff --git a/src/dynarec/rv64/dynarec_rv64_avx.c b/src/dynarec/rv64/dynarec_rv64_avx.c index f62c272d2..d2bbd7834 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx.c +++ b/src/dynarec/rv64/dynarec_rv64_avx.c @@ -56,12 +56,13 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F) && (vex.p == VEX_P_66)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -69,12 +70,13 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_66_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_66_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F) && (vex.p == VEX_P_F2)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -82,12 +84,13 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_F2_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_F2_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F) && (vex.p == VEX_P_F3)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -95,12 +98,13 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_F3_0F_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_F3_0F(dyn, addr, ip, ninst, vex, ok, need_epilog); } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_66)) { if (cpuext.vector && cpuext.vlen >= 32) { @@ -108,35 +112,41 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n retaddr = dynarec64_AVX_66_0F38_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_66_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_NONE)) + } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_NONE)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F2)) + } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F2)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_F2_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F3)) + } else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F3)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_F3_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog); - else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_66)) { + } else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_66)) { if (cpuext.vector && cpuext.vlen >= 32) { uintptr_t vaddr = addr; retaddr = dynarec64_AVX_66_0F3A_vector(dyn, addr, ip, ninst, vex, ok, need_epilog); if (retaddr) { if (dyn->vector_sew != VECTOR_SEWNA) - avx_set_vector_width(dyn, ninst, x1, dyn->vector_sew, 16); + dyn->vtype_restore = dyn->vector_sew; } else { addr = vaddr; - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); } } + if (!retaddr) avx_sync_upper_vector(dyn, ninst, x1, 0); addr = retaddr ? retaddr : dynarec64_AVX_66_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog); - } else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_F2)) + } else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_F2)) { + avx_sync_upper_vector(dyn, ninst, x1, 0); addr = dynarec64_AVX_F2_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog); - else { + } else { DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_0f.c index c847d178c..af99f8d10 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f.c @@ -309,7 +309,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in case 0x50: INST_NAME("VMOVMSKPS Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEX(x2, 0, vex.l ? 24 : 8); XOR(gd, gd, gd); for (int i = 0; i < 4; ++i) { @@ -389,7 +389,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in s0 = fpu_get_scratch(dyn); s1 = fpu_get_scratch(dyn); // 1.0f v0 = fpu_get_scratch(dyn); // 0.0f - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(s1, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) { FMVWX(v0, xZR); @@ -462,7 +462,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in GETGY(); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); - LUI(x3, 0x3f800); + MOV32w(x3, 0x3F800000); FMVWX(d0, x3); // 1.0f if (!BOX64ENV(dynarec_fastnan)) MOV32w(x6, 0x00400000); @@ -940,40 +940,20 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vxoffset + i * 4); - if (!BOX64ENV(dynarec_fastnan)) { - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s1, s0); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gdoffset + i * 4); - B(4 + 4); - FSW(s1, gback, gdoffset + i * 4); - } else { - FMINS(s1, s1, s0); - FSW(s1, gback, gdoffset + i * 4); - } + FLTS(x3, s1, s0); + BNEZ(x3, 8); + FMVS(s1, s0); + FSW(s1, gback, gdoffset + i * 4); } if (vex.l) { GETEY(); for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vyoffset + i * 4); - if (!BOX64ENV(dynarec_fastnan)) { - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s1, s0); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gyoffset + i * 4); - B(4 + 4); - FSW(s1, gback, gyoffset + i * 4); - } else { - FMINS(s1, s1, s0); - FSW(s1, gback, gyoffset + i * 4); - } + FLTS(x3, s1, s0); + BNEZ(x3, 8); + FMVS(s1, s0); + FSW(s1, gback, gyoffset + i * 4); } } else YMM0(gd); @@ -1051,14 +1031,9 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vxoffset + i * 4); - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s0, s1); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gdoffset + i * 4); - B(4 + 4); + FLTS(x3, s0, s1); + BNEZ(x3, 8); + FMVS(s1, s0); FSW(s1, gback, gdoffset + i * 4); } if (vex.l) { @@ -1066,14 +1041,9 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in for (int i = 0; i < 4; ++i) { FLW(s0, wback, fixedaddress + i * 4); FLW(s1, vback, vyoffset + i * 4); - FEQS(x3, s0, s0); - FEQS(x4, s1, s1); - AND(x3, x3, x4); - FLTS(x5, s0, s1); - AND(x3, x3, x5); - BNEZ(x3, 4 + 4 * 2); - FSW(s0, gback, gyoffset + i * 4); - B(4 + 4); + FLTS(x3, s0, s1); + BNEZ(x3, 8); + FMVS(s1, s0); FSW(s1, gback, gyoffset + i * 4); } } else diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_0f38.c index 882a157a0..6fcc85a53 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f38.c @@ -61,7 +61,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("ANDN Gd, Vd, Ed"); nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDd; GETED(0); GETVD; ANDN(gd, ed, vd, x5); @@ -88,7 +88,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BLSR Vd, Ed"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); GETED(0); - GETVD; + GETVDsd; if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -116,7 +116,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BLSMSK Vd, Ed"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); GETED(0); - GETVD; + GETVDsd; if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -141,7 +141,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BLSI Vd, Ed"); SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); GETED(0); - GETVD; + GETVDsd; if (!rex.w) { ZEXTW2(x4, ed); ed = x4; @@ -174,7 +174,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BZHI Gd, Ed, Vd"); nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDd; GETED(0); GETVD; CLEAR_FLAGS(); @@ -208,7 +208,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, INST_NAME("BEXTR Gd, Ed, Vd"); nextop = F8; SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x4, vd, 0xff); // start diff --git a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c index a1e7c630d..6ba9f356c 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_0f_vector.c @@ -28,7 +28,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t uint8_t nextop, u8; uint8_t gd, ed; int v0, v1, v2; - int q0, q1, q2, d0; + int q0, q1, q2, d0, d1; + int j64; uint64_t selectors; int64_t fixedaddress; rex_t rex = vex.rex; @@ -38,15 +39,27 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t MAYUSE(q1); MAYUSE(q2); MAYUSE(d0); + MAYUSE(d1); + MAYUSE(j64); switch (opcode) { case 0x10: INST_NAME("VMOVUPS Gx, Ex"); nextop = F8; - GETEY_vector(v1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); - VMV_V_V(v0, v1); - PUTGY_vector(v0, VECTOR_SEW8); + if (!MODREG) { + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VLE8_V(v0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16 << vex.l, VECTOR_SEW8); + } else { + GETEY_vector(v1, 0, VECTOR_SEW8); + GETGY_empty_vector(v0); + VMV_V_V(v0, v1); + PUTGY_vector(v0, VECTOR_SEW8); + } break; case 0x11: INST_NAME("VMOVUPS Ex, Gx"); @@ -78,16 +91,15 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VMOVLPS Gx, Vx, Ex"); SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - if (fixedaddress) { ADDI(x4, ed, fixedaddress); ed = x4; fixedaddress = 0; } - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); - VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + LD(x4, ed, fixedaddress); + VMV_S_X(q1, x4); } GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); VMV_V_V(v0, q1); - VSLIDEUP_VI(v0, q2, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q2, 1, VECTOR_UNMASKED); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x13: @@ -103,9 +115,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x14: INST_NAME("VUNPCKLPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -113,8 +123,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VAND_VI(v1, q2, 4, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); @@ -122,9 +132,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x15: INST_NAME("VUNPCKHPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -133,8 +141,8 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VADD_VV(q2, q2, v1, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VI(q2, q2, 2, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); @@ -152,14 +160,13 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VMOVHPS Gx, Vx, Ex"); SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - if (fixedaddress) { ADDI(x4, ed, fixedaddress); ed = x4; fixedaddress = 0; } - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); - VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + LD(x4, ed, fixedaddress); + VMV_S_X(q1, x4); } GETGY_empty_vector(v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VMV_V_V(v0, q0); - VSLIDEUP_VI(v0, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x17: @@ -207,14 +214,59 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t SMWRITE2(); break; case 0x2E: - return 0; case 0x2F: - return 0; + if (opcode == 0x2F) { + INST_NAME("VCOMISS Gx, Ex"); + } else { + INST_NAME("VUCOMISS Gx, Ex"); + } + SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + SET_DFNONE(); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW32); + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW32); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + FLW(d1, ed, fixedaddress); + } + CLEAR_FLAGS(); + IFX (X_ZF | X_PF | X_CF) { + FEQS(x3, d0, d0); + FEQS(x2, d1, d1); + AND(x2, x2, x3); + BNE_MARK(x2, xZR); + ORI(xFlags, xFlags, (1 << F_ZF) | (1 << F_PF) | (1 << F_CF)); + B_NEXT_nocond; + } + MARK; + IFX (X_CF) { + FLTS(x2, d0, d1); + BEQ_MARK2(x2, xZR); + ORI(xFlags, xFlags, 1 << F_CF); + B_NEXT_nocond; + } + MARK2; + IFX (X_ZF) { + FEQS(x2, d0, d1); + CBZ_NEXT(x2); + ORI(xFlags, xFlags, 1 << F_ZF); + } + break; case 0x50: INST_NAME("VMOVMSKPS Gd, Ex"); nextop = F8; GETEY_vector(q0, 0, VECTOR_SEW32); - GETGD; + GETGDd; VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); VMV_X_S(gd, VMASK); ANDI(gd, gd, vex.l ? 0xff : 0x0f); @@ -235,7 +287,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETEY_vector(v1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); VFSQRT_V(v0, v1, VECTOR_UNMASKED); VFDIV_VV(v0, v2, v0, VECTOR_UNMASKED); @@ -248,7 +300,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETEY_vector(v1, 0, VECTOR_SEW32); GETGY_empty_vector(v0); v2 = fpu_get_scratch(dyn); - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); VMV_V_X(v2, x4); VFDIV_VV(v0, v2, v1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -256,18 +308,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x54: INST_NAME("VANDPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x55: INST_NAME("VANDNPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); VAND_VV(v0, v0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -275,18 +323,14 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t case 0x56: INST_NAME("VORPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x57: INST_NAME("VXORPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -294,9 +338,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -304,9 +346,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -338,51 +378,41 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t nextop = F8; GETEY_vector(q0, 0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x6, x4); VFCVT_F_X_V(v0, q0, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5C: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5D: INST_NAME("VMINPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - VMV_V_V(v0, q0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x5F: INST_NAME("VMAXPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - VMV_V_V(v0, q0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x77: @@ -390,21 +420,22 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t UDF(); break; } - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); if (vex.l) { INST_NAME("VZEROALL"); - for (int i = 0; i < (rex.is32bits ? 8 : 16); ++i) { - SD(xZR, xEmu, offsetof(x64emu_t, xmm[i]) + 0); - SD(xZR, xEmu, offsetof(x64emu_t, xmm[i]) + 8); - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); - } } else { INST_NAME("VZEROUPPER"); - for (int i = 0; i < (rex.is32bits ? 8 : 16); ++i) { - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); - SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL4, 8); + v1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL4); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + for (int off = 0; off < (rex.is32bits ? 8 : 16) * 16; off += 128) { + if (vex.l) { + ADDI(x4, xEmu, offsetof(x64emu_t, xmm) + off); + VSE8_V(v1, x4, VECTOR_UNMASKED, VECTOR_NFIELD1); } + ADDI(x4, xEmu, offsetof(x64emu_t, ymm) + off); + VSE8_V(v1, x4, VECTOR_UNMASKED, VECTOR_NFIELD1); } break; case 0xAE: @@ -456,7 +487,7 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ANDI(x5, x5, 4); OR(x4, x4, x5); SRLIW(x5, x3, 4); - ANDI(x5, x5, 2); + ANDI(x5, x5, 1); OR(x4, x4, x5); } SW(x4, ed, fixedaddress); @@ -475,14 +506,16 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t GETGY_empty_vector(v0); q2 = fpu_get_scratch(dyn); d0 = fpu_get_scratch(dyn); - VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); - VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); - VMAND_MM(q2, q2, d0); switch (u8 & 0xf) { case 0x0: VMFEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; case 0x1: VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; case 0x2: VMFLE_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; - case 0x3: VMNAND_MM(VMASK, q2, q2); break; + case 0x3: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMNAND_MM(VMASK, q2, q2); + break; case 0x4: VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); @@ -495,8 +528,16 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VMFLE_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); break; - case 0x7: VMAND_MM(VMASK, q2, q2); break; + case 0x7: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMAND_MM(VMASK, q2, q2); + break; case 0x8: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, q2, q2); VMOR_MM(VMASK, VMASK, d0); @@ -509,15 +550,28 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t VMFLT_VV(d0, q1, q0, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); break; - case 0xb: VMXOR_MM(VMASK, q2, q2); break; + case 0xb: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMXOR_MM(VMASK, q2, q2); + break; case 0xc: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); VMNAND_MM(VMASK, d0, d0); VMAND_MM(VMASK, VMASK, q2); break; case 0xd: VMFLE_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; case 0xe: VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; - case 0xf: VMXNOR_MM(VMASK, q2, q2); break; + case 0xf: + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); + VMAND_MM(q2, q2, d0); + VMXNOR_MM(VMASK, q2, q2); + break; } VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -527,26 +581,48 @@ uintptr_t dynarec64_AVX_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t INST_NAME("VSHUFPS Gx, Vx, Ex, Ib"); nextop = F8; GETVY_vector(q0, VECTOR_SEW32); + if (!vex.l && MODREG && ((nextop & 7) + (rex.b << 3)) == vex.v) { + u8 = F8; + MOV64x(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48)); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + q2 = fpu_get_scratch(dyn); + VMV_S_X(q2, x4); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16); + GETGY_empty_vector(v0); + if (v0 == q0) { + v2 = fpu_get_scratch(dyn); + VRGATHEREI16_VV(v2, q0, q2, VECTOR_UNMASKED); + v0 = v2; + } else { + VRGATHEREI16_VV(v0, q0, q2, VECTOR_UNMASKED); + } + PUTGY_vector(v0, VECTOR_SEW32); + break; + } GETEY_vector(q1, 1, VECTOR_SEW32); u8 = F8; - selectors = 0; - for (int i = 0; i < (4 << vex.l); ++i) { - int lane = i & ~3; - int pos = i & 3; - int selector = lane + ((u8 >> (pos * 2)) & 3); - if (pos >= 2) selector |= 0x80; - selectors |= (uint64_t)selector << (i * 8); - } GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); q2 = fpu_get_scratch(dyn); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - for (int i = 0; i < (4 << vex.l); ++i) { - int selector = selectors >> (i * 8); - MOV32w(x4, selector & 0x1f); - VRGATHER_VX(q2, (selector & 0x80) ? q1 : q0, x4, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v0, q2); + v1 = fpu_get_scratch(dyn); + v2 = fpu_get_scratch(dyn); + MOV64xs(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48), x3); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + if (vex.l) { + VMV_V_X(q2, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VOR_VI(q2, q2, 4, VECTOR_MASKED); + } else { + VMV_S_X(q2, x4); } + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); + VRGATHEREI16_VV(v1, q0, q2, VECTOR_UNMASKED); + VRGATHEREI16_VV(v2, q1, q2, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(vex.l ? 0xcc : 0x0c, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); break; default: diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c index cd8d1e6a3..bb02b898b 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f.c @@ -171,6 +171,19 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SD(x3, gback, gdoffset + 8); YMM0(gd); break; + case 0x17: + INST_NAME("VMOVHPD Ex, Gx"); + nextop = F8; + if (MODREG) { + DEFAULT; + return addr; + } + GETGX(); + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0); + LD(x3, gback, gdoffset + 8); + SD(x3, wback, fixedaddress); + SMWRITE2(); + break; case 0x28: INST_NAME("VMOVAPD Gx, Ex"); nextop = F8; @@ -273,7 +286,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x50: INST_NAME("VMOVMSKPD Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEX(x1, 0, vex.l ? 24 : 8); XOR(gd, gd, gd); for (int i = 0; i < 2; ++i) { @@ -589,7 +602,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGX(); d0 = fpu_get_scratch(dyn); u8 = sse_setround(dyn, ninst, x6, x4); - if (!BOX64ENV(dynarec_fastnan)) LUI(x7, 0x7fc00); + if (!BOX64ENV(dynarec_fastnan)) MOV32w(x7, 0x7FC00000); for (int i = 0; i < 2; ++i) { FLD(d0, wback, fixedaddress + i * 8); if (!BOX64ENV(dynarec_fastnan)) { @@ -650,7 +663,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLS(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); // INT32_MIN SW(x3, gback, gdoffset + 4 * i); } if (vex.l) { @@ -660,7 +673,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLS(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); // INT32_MIN SW(x3, gback, gyoffset + 4 * i); } } else @@ -738,28 +751,20 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v0 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vxoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v0, v1); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vxoffset + 8 * i); + FLTD(x3, v1, v0); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gdoffset + 8 * i); } if (vex.l) { GETEY(); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vyoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v0, v1); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vyoffset + 8 * i); + FLTD(x3, v1, v0); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gyoffset + 8 * i); } @@ -837,28 +842,20 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v0 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vxoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v1, v0); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vxoffset + 8 * i); + FLTD(x3, v0, v1); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gdoffset + 8 * i); } if (vex.l) { GETEY(); for (int i = 0; i < 2; ++i) { - FLD(v0, vback, vyoffset + 8 * i); - FLD(v1, wback, fixedaddress + 8 * i); - FEQD(x3, v0, v0); - FEQD(x4, v1, v1); - AND(x3, x3, x4); - BEQ(x3, xZR, 4 + 3 * 4); - FLTD(x3, v1, v0); - BEQ(x3, xZR, 4 + 4); // continue + FLD(v0, wback, fixedaddress + 8 * i); + FLD(v1, vback, vyoffset + 8 * i); + FLTD(x3, v0, v1); + BNEZ(x3, 8); FMVD(v1, v0); FSD(v1, gback, gyoffset + 8 * i); } @@ -1187,9 +1184,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGY(); GETVX(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); if (gd == ed) { ADDI(x5, xEmu, offsetof(x64emu_t, scratch)); LD(x3, wback, fixedaddress + 0); @@ -2268,7 +2264,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0xC5: INST_NAME("VPEXTRW Gd, Ex, Ib"); nextop = F8; - GETGD; + GETGDd; GETEX(x2, 1, 14); u8 = (F8) & 7; LHU(gd, wback, fixedaddress + 2 * u8); @@ -2540,7 +2536,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, nextop = F8; GETEX(x2, 0, vex.l ? 28 : 12); GETGD; - MOV64x(x5, 0x8080808080808080); + MOV64xs(x5, 0x8080808080808080, x3); MOV64x(x6, 0x0002040810204081); LD(x1, wback, fixedaddress + 0); AND(x1, x1, x5); @@ -3064,9 +3060,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGY(); GETVX(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LH(x3, vback, vxoffset + i * 2); LH(x4, wback, fixedaddress + i * 2); @@ -3183,9 +3178,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, GETGY(); GETVX(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LH(x3, vback, vxoffset + i * 2); LH(x4, wback, fixedaddress + i * 2); @@ -3660,8 +3654,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FLD(d0, wback, fixedaddress + 8 * i); FCVTLD(x3, d0, RD_RTZ); SEXT_W(x5, x3); - BEQ(x5, x3, 8); - LUI(x3, 0x80000); + BEQ(x5, x3, 20); + LWU(x5, xEmu, offsetof(x64emu_t, mxcsr)); + ORI(x5, x5, 1); + SW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 4 * i); } if (vex.l) { @@ -3670,8 +3667,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FLD(d0, wback, fixedaddress + 8 * i); FCVTLD(x3, d0, RD_RTZ); SEXT_W(x5, x3); - BEQ(x5, x3, 8); - LUI(x3, 0x80000); + BEQ(x5, x3, 20); + LWU(x5, xEmu, offsetof(x64emu_t, mxcsr)); + ORI(x5, x5, 1); + SW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 8 + 4 * i); } } else { @@ -3682,6 +3682,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, break; case 0xF7: INST_NAME("VMASKMOVDQU Gx, Ex"); + UP32_READ(xRDI); nextop = F8; GETEX(x1, 0, 15); GETGX(); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c index 1adec115e..490e9ab16 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38.c @@ -111,9 +111,8 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETVX(); GETGY(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); if (gd == ed) { ADDI(x5, xEmu, offsetof(x64emu_t, scratch)); LD(x3, wback, fixedaddress + 0); @@ -260,9 +259,8 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETVX(); GETGY(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); for (int i = 0; i < 8; ++i) { LBU(x3, vback, vxoffset + i * 2); LB(x4, wback, fixedaddress + i * 2); @@ -302,9 +300,8 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETVX(); GETGY(); GETVY(); - LUI(x6, 0xFFFF8); // -32768 - LUI(x7, 0x8); // 32768 - ADDIW(x7, x7, -1); + MOV64x(x6, -32768); + MOV32w(x7, 0x7FFF); if (gd == ed) { ADDI(x5, xEmu, offsetof(x64emu_t, scratch)); LD(x3, wback, fixedaddress + 0); @@ -585,8 +582,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 4 * i); ANDI(x4, x4, 3); - SLLI(x4, x4, 2); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 2, x4); LWU(x5, x4, offsetof(x64emu_t, scratch) + 0); SW(x5, gback, gdoffset + 4 * i); } @@ -604,8 +600,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 4 * i); ANDI(x4, x4, 3); - SLLI(x4, x4, 2); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 2, x4); LWU(x5, x4, offsetof(x64emu_t, scratch) + 0); SW(x5, gback, gyoffset + 4 * i); } @@ -631,8 +626,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LD(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 8 * i); SRLI(x4, x4, 1); ANDI(x4, x4, 1); - SLLI(x4, x4, 3); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 3, x4); LD(x5, x4, offsetof(x64emu_t, scratch) + 0); SD(x5, gback, gdoffset + 8 * i); } @@ -651,8 +645,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i LD(x4, xEmu, offsetof(x64emu_t, scratch) + 16 + 8 * i); SRLI(x4, x4, 1); ANDI(x4, x4, 1); - SLLI(x4, x4, 3); - ADD(x4, x4, xEmu); + ADDSL(x4, xEmu, x4, 3, x4); LD(x5, x4, offsetof(x64emu_t, scratch) + 0); SD(x5, gback, gyoffset + 8 * i); } @@ -727,16 +720,14 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x3, vback, vxoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gdoffset + 4 * i); } for (int i = 0; i < 4; ++i) { LWU(x3, vback, vyoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gyoffset + 4 * i); } @@ -1232,8 +1223,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i GETEX(x2, 0, vex.l ? 28 : 12); GETGX(); GETGY(); - LUI(x5, 0x10); // 65536 - ADDIW(x5, x5, -1); + MOV32w(x5, 0xFFFF); if (MODREG && ed == vex.v) { for (int i = 0; i < 4; ++i) { LW(x3, vback, vxoffset + i * 4); @@ -1474,16 +1464,14 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i for (int i = 0; i < 4; ++i) { LWU(x3, vback, vxoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gdoffset + 4 * i); } for (int i = 0; i < 4; ++i) { LWU(x3, vback, vyoffset + 4 * i); ANDI(x3, x3, 7); - SLLI(x3, x3, 2); - ADD(x4, wback, x3); + ADDSL(x4, wback, x3, 2, x3); LWU(x5, x4, fixedaddress); SW(x5, gback, gyoffset + 4 * i); } @@ -1492,7 +1480,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMINSB Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 31 : 15); GETVX(); GETGY(); GETVY(); @@ -1562,7 +1550,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMINUW Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 30 : 14); GETVX(); GETGY(); GETVY(); @@ -1632,7 +1620,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMAXSB Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 31 : 15); GETVX(); GETGY(); GETVY(); @@ -1702,7 +1690,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i INST_NAME("VPMAXUW Gx, Vx, Ex"); nextop = F8; GETGX(); - GETEX(x2, 0, vex.l ? 28 : 12); + GETEX(x2, 0, vex.l ? 30 : 14); GETVX(); GETGY(); GETVY(); @@ -1826,7 +1814,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i nextop = F8; GETEX(x2, 0, 14); GETGX(); - ADDI(x6, xZR, 0xffff); + MOV32w(x6, 0xffff); ADDI(x7, xZR, 0); for (int i = 0; i < 8; ++i) { LHU(x3, wback, fixedaddress + 2 * i); @@ -2194,7 +2182,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDC: INST_NAME("VAESENC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2266,7 +2254,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDD: INST_NAME("VAESENCLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2341,7 +2329,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i if (vex.l) { DEFAULT; } - if (cpuext.zvkned) { + if (cpuext.zvkned && cpuext.vlen >= 32 && !vex.l) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v1 = fpu_get_scratch(dyn); @@ -2373,7 +2361,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDE: INST_NAME("VAESDEC Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2452,7 +2440,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xDF: INST_NAME("VAESDECLAST Gx, Vx, Ex"); nextop = F8; - if (cpuext.zvkned && (!vex.l || cpuext.vlen >= 32)) { + if (cpuext.zvkned && cpuext.vlen >= 32) { gd = ((nextop & 0x38) >> 3) + (rex.r << 3); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); v0 = fpu_get_scratch(dyn); @@ -2524,7 +2512,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF7: INST_NAME("SHLX Gd, Ed, Vd"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x5, vd, rex.w ? 0x3f : 0x1f); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c index 1c14dbe33..46536dd07 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f38_vector.c @@ -26,7 +26,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint uint8_t opcode = F8; uint8_t nextop; - uint8_t gd, ed; + uint8_t gd, ed, vd, wback; + uint8_t u8; int v0, v1, v2; int q0, q1, q2, q3, q4, q5; int sew; @@ -35,6 +36,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint rex_t rex = vex.rex; MAYUSE(v1); + MAYUSE(u8); MAYUSE(q0); MAYUSE(q1); MAYUSE(q2); @@ -42,11 +44,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint switch (opcode) { case 0x00: INST_NAME("VPSHUFB Gx, Vx, Ex"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); @@ -59,16 +58,101 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(v2, q1); VAND_VX(v2, v2, x5, VECTOR_UNMASKED); VSLIDEDOWN_VI(q2, v1, 16, VECTOR_UNMASKED); - VSLIDEUP_VI(v2, q2, 16, VECTOR_UNMASKED); - VRGATHER_VV(v0, q0, v2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v2, q2, 16, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; + +#define GO(SEW, OP) \ + do { \ + int E_ = 16 >> (SEW); \ + int S_ = (vex.l ? 2 : 1) * E_; \ + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); \ + q5 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); \ + q3 = fpu_get_scratch(dyn); \ + q4 = fpu_get_scratch(dyn); \ + vector_vsetvli(dyn, ninst, x1, (SEW), VECTOR_LMUL1, S_ / E_); \ + VMV_V_V(q2, q0); \ + if (q1 & 1) VMV_V_V(q5, q1); \ + vector_vsetvli(dyn, ninst, x1, (SEW), VECTOR_LMUL2, 2 * S_ / E_); \ + VSLIDEUP_VI_SAFE(q2, (q1 & 1) ? q5 : q1, S_, VECTOR_UNMASKED); \ + vector_vsetvli(dyn, ninst, x1, (SEW), VECTOR_LMUL1, S_ / E_); \ + VNSRL_WI(q3, q2, 0, VECTOR_UNMASKED); \ + if ((SEW) == VECTOR_SEW16) { \ + VNSRL_WI(q4, q2, 16, VECTOR_UNMASKED); \ + } else { \ + ADDI(x4, xZR, 32); \ + VNSRL_WX(q4, q2, x4, VECTOR_UNMASKED); \ + } \ + if (vex.l) { \ + OP(q3, q3, q4, VECTOR_UNMASKED); \ + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); \ + MOV64x(x4, 0x0003000100020000ULL); \ + VMV_S_X(q4, x4); \ + VRGATHEREI16_VV(v0, q3, q4, VECTOR_UNMASKED); \ + } else { \ + OP(v0, q3, q4, VECTOR_UNMASKED); \ + } \ + PUTGY_vector(v0, (SEW)); \ + } while (0) + + case 0x01: + INST_NAME("VPHADDW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VADD_VV); + break; + case 0x02: + INST_NAME("VPHADDD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 0); + GO(VECTOR_SEW32, VADD_VV); + break; + case 0x03: + INST_NAME("VPHADDSW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VSADD_VV); + break; + case 0x04: + INST_NAME("VPMADDUBSW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VWMULSU_VV(q2, q1, q0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, vex.l ? 2 : 1); + VNSRL_WI(q3, q2, 0, VECTOR_UNMASKED); + VNSRL_WI(q4, q2, 16, VECTOR_UNMASKED); + VSADD_VV(v0, q3, q4, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW16); + break; + case 0x05: + INST_NAME("VPHSUBW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VSUB_VV); + break; + case 0x06: + INST_NAME("VPHSUBD Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 0); + GO(VECTOR_SEW32, VSUB_VV); + break; + case 0x07: + INST_NAME("VPHSUBSW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 0); + GO(VECTOR_SEW16, VSSUB_VV); + break; +#undef GO + case 0x08: INST_NAME("VPSIGNB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW8); VMV_V_V(v0, q0); VMSLT_VX(VMASK, q1, xZR, VECTOR_UNMASKED); VRSUB_VX(v0, q0, xZR, VECTOR_MASKED); @@ -79,9 +163,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x09: INST_NAME("VPSIGNW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW16); VMV_V_V(v0, q0); VMSLT_VX(VMASK, q1, xZR, VECTOR_UNMASKED); VRSUB_VX(v0, q0, xZR, VECTOR_MASKED); @@ -92,9 +174,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0A: INST_NAME("VPSIGND Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VMV_V_V(v0, q0); VMSLT_VX(VMASK, q1, xZR, VECTOR_UNMASKED); VRSUB_VX(v0, q0, xZR, VECTOR_MASKED); @@ -105,9 +185,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0B: INST_NAME("VPMULHRSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMUL_VV(q2, q0, q1, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2 << vex.l); @@ -120,30 +198,28 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0C: INST_NAME("VPERMILPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 4, VECTOR_UNMASKED); - VAND_VI(q1, q1, 3, VECTOR_UNMASKED); - VADD_VV(q1, q1, q2, VECTOR_UNMASKED); - VRGATHER_VV(v0, q0, q1, VECTOR_UNMASKED); + VAND_VI(q3, q1, 3, VECTOR_UNMASKED); + VADD_VV(q3, q3, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, q3, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x0D: INST_NAME("VPERMILPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 2, VECTOR_UNMASKED); - VSRL_VI(q1, q1, 1, VECTOR_UNMASKED); - VAND_VI(q1, q1, 1, VECTOR_UNMASKED); - VADD_VV(q1, q1, q2, VECTOR_UNMASKED); - VRGATHER_VV(v0, q0, q1, VECTOR_UNMASKED); + VSRL_VI(q3, q1, 1, VECTOR_UNMASKED); + VAND_VI(q3, q3, 1, VECTOR_UNMASKED); + VADD_VV(q3, q3, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q0, q3, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x0E: @@ -177,29 +253,56 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SET_FLAGS_EQZ(x4, F_CF, x5); } break; + case 0x17: + INST_NAME("VPTEST Gx, Ex"); + nextop = F8; + SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); + GETGY_vector(q0, VECTOR_SEW32); + GETEY_vector(q1, 0, VECTOR_SEW32); + v0 = fpu_get_scratch(dyn); + CLEAR_FLAGS(); + SET_DFNONE(); + IFX (X_ZF) { + VAND_VV(v0, q0, q1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, v0, xZR, VECTOR_UNMASKED); + VMV_X_S(x4, VMASK); + ANDI(x4, x4, (1 << (4 << vex.l)) - 1); + SET_FLAGS_EQZ(x4, F_ZF, x5); + } + IFX (X_CF) { + VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); + VAND_VV(v0, v0, q1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, v0, xZR, VECTOR_UNMASKED); + VMV_X_S(x4, VMASK); + ANDI(x4, x4, (1 << (4 << vex.l)) - 1); + SET_FLAGS_EQZ(x4, F_CF, x5); + } + break; case 0x16: if (!vex.l) return 0; INST_NAME("VPERMPS Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - VAND_VI(q0, q0, 7, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q0, VECTOR_UNMASKED); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + VAND_VI(q2, q0, 7, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x18: INST_NAME("VBROADCASTSS Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { q0 = fpu_get_scratch(dyn); ed = (nextop & 7) + (rex.b << 3); avx_load_reg_vector(dyn, ninst, x1, q0, ed, 16, VECTOR_SEW32); - VMV_X_S(x4, q0); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + } + GETGY_empty_vector(v0); + if (MODREG) { + VMV_X_S(x4, q0); + } else { LW(x4, ed, fixedaddress); } SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); @@ -209,15 +312,18 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x19: INST_NAME("VBROADCASTSD Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { q0 = fpu_get_scratch(dyn); ed = (nextop & 7) + (rex.b << 3); avx_load_reg_vector(dyn, ninst, x1, q0, ed, 16, VECTOR_SEW64); - VMV_X_S(x4, q0); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + } + GETGY_empty_vector(v0); + if (MODREG) { + VMV_X_S(x4, q0); + } else { LD(x4, ed, fixedaddress); } SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); @@ -241,7 +347,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); VMV_V_V(v0, q0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); - VSLIDEUP_VI(v0, q0, 16, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q0, 16, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x1C: @@ -279,6 +385,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -288,6 +395,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VSEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -297,6 +405,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 2 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF8(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -306,6 +415,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -315,6 +425,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -324,6 +435,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW32, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VSEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -331,15 +443,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x28: INST_NAME("VPMULDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); VID_V(v2, VECTOR_UNMASKED); VSLL_VI(v2, v2, 1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, v2, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, v2, VECTOR_UNMASKED); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); VWMUL_VV(q2, v1, v0, VECTOR_UNMASKED); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); @@ -349,9 +459,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x29: INST_NAME("VPCMPEQQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -371,9 +479,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x2B: INST_NAME("VPACKUSDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); @@ -383,18 +489,18 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); VSLIDEDOWN_VI(q2 + 1, q2, 4, VECTOR_UNMASKED); // hi[0..3] = a[4..7] avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); - VSLIDEUP_VI(q2, v1, 4, VECTOR_UNMASKED); // lo[4..7] = b[0..3] + VSLIDEUP_VI_SAFE(q2, v1, 4, VECTOR_UNMASKED); // lo[4..7] = b[0..3] vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); VSLIDEDOWN_VI(v1 + 1, v1, 4, VECTOR_UNMASKED); // v1 hi[0..3] = b[4..7] avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); - VSLIDEUP_VI(q2 + 1, v1 + 1, 4, VECTOR_UNMASKED); // hi[4..7] = b[4..7] + VSLIDEUP_VI_SAFE(q2 + 1, v1 + 1, 4, VECTOR_UNMASKED); // hi[4..7] = b[4..7] if (cpuext.vlen > 32) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 4); - VSLIDEUP_VI(q2, q2 + 1, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, q2 + 1, 8, VECTOR_UNMASKED); } } else { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 2); - VSLIDEUP_VI(q2, v1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 4, VECTOR_UNMASKED); } avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VNCLIPU_WI(v0, q2, 0, VECTOR_UNMASKED); @@ -405,6 +511,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETVY_vector(q0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -425,6 +532,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETVY_vector(q0, VECTOR_SEW64); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -469,6 +577,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -478,6 +587,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VZEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -487,6 +597,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW8, 2 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF8(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -496,6 +607,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); @@ -505,6 +617,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW16, 4 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF4(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -514,6 +627,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint nextop = F8; GETEY_vector_w(q0, 0, VECTOR_SEW32, 8 << vex.l); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); VZEXT_VF2(v0, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -522,19 +636,16 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VPERMD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); - VAND_VI(q0, q0, 7, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q0, VECTOR_UNMASKED); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + VAND_VI(q2, q0, 7, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x37: INST_NAME("VPCMPGTQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -543,81 +654,63 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x38: INST_NAME("VPMINSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x39: INST_NAME("VPMINSD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x3D: INST_NAME("VPMAXSD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x3A: INST_NAME("VPMINUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0x3B: INST_NAME("VPMINUD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x3C: INST_NAME("VPMAXSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x3E: INST_NAME("VPMAXUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0x3F: INST_NAME("VPMAXUD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x40: INST_NAME("VPMULLD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -625,18 +718,14 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSRLVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 64); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); VSRL_VV(v0, q0, q1, VECTOR_MASKED); PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 32); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); @@ -648,9 +737,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (rex.w) return 0; INST_NAME("VPSRAVD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); MOV32w(x4, 31); VMINU_VX(q2, q1, x4, VECTOR_UNMASKED); @@ -661,18 +748,14 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VPSLLVD/Q Gx, Vx, Ex"); nextop = F8; if (rex.w) { - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 64); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); VSLL_VV(v0, q0, q1, VECTOR_MASKED); PUTGY_vector(v0, VECTOR_SEW64); } else { - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW32); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); MOV32w(x4, 32); VMSLTU_VX(VMASK, q1, x4, VECTOR_UNMASKED); @@ -683,7 +766,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x58: INST_NAME("VPBROADCASTD Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -694,6 +776,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LW(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW32); @@ -701,7 +784,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x59: INST_NAME("VPBROADCASTQ Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -712,6 +794,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LD(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW64); @@ -733,13 +816,12 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETGY_empty_vector(v0); VMV_V_V(v0, q0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); - VSLIDEUP_VI(v0, q0, 16, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q0, 16, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0x78: INST_NAME("VPBROADCASTB Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -750,6 +832,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LBU(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW8); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW8); @@ -757,7 +840,6 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x79: INST_NAME("VPBROADCASTW Gx, Ex"); nextop = F8; - GETGY_empty_vector(v0); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q0 = fpu_get_scratch(dyn); @@ -768,6 +850,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); LHU(x4, ed, fixedaddress); } + GETGY_empty_vector(v0); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); VMV_V_X(v0, x4); PUTGY_vector(v0, VECTOR_SEW16); @@ -778,6 +861,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (rex.w) { GETVY_vector(q0, VECTOR_SEW64); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -795,6 +879,7 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint } else { GETVY_vector(q0, VECTOR_SEW32); GETGY_empty_vector(v0); + if (v0 == q0) v0 = fpu_get_scratch(dyn); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); if (MODREG) { @@ -833,6 +918,52 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SMWRITE2(); } break; + case 0x92: + INST_NAME("VGATHERDPS Gx, VSIB, Vx"); + nextop = F8; + if (rex.w || ((nextop & 7) != 4) || MODREG) return 0; + u8 = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + if ((u8 & 7) == 5 && !(nextop & 0xC0)) { + int64_t i64 = F32S64; + MOV64x(x5, i64); + } else { + ed = TO_NAT((u8 & 7) + (rex.b << 3)); + MV(x5, ed); + } + if (nextop & 0x40) + j64 = F8S; + else if (nextop & 0x80) + j64 = F32S; + else + j64 = 0; + if (j64) { + if (j64 >= -2048 && j64 < 2048) { + ADDI(x5, x5, j64); + } else { + MOV64x(x4, j64); + ADD(x5, x5, x4); + } + } + ed = ((u8 >> 3) & 7) + (rex.x << 3); + SMREAD(); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW32); + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16 << vex.l, VECTOR_SEW32); + GETGY_vector(q2, VECTOR_SEW32); + q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL2, vex.l ? 4 : 2); + VSEXT_VF2(q4, q1, VECTOR_UNMASKED); + if (u8 >> 6) VSLL_VI(q4, q4, u8 >> 6, VECTOR_UNMASKED); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); + VLUXEI64_V(q2, q4, x5, VECTOR_MASKED, VECTOR_NFIELD1); + VAND_VX(q0, q0, xZR, VECTOR_MASKED); + PUTGY_vector(q2, VECTOR_SEW32); + gd = vex.v; + PUTGY_vector(q0, VECTOR_SEW32); + break; case 0x98: INST_NAME("VFMADD132PS/D Gx, Vx, Ex"); nextop = F8; @@ -841,6 +972,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFMACC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -853,8 +987,11 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); + v1 = fpu_get_scratch(dyn); VFMACC_VV(v0, q2, q1, VECTOR_UNMASKED); VMV_V_V(v1, q0); VFMSAC_VV(v1, q2, q1, VECTOR_UNMASKED); @@ -870,8 +1007,11 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); + v1 = fpu_get_scratch(dyn); VFMSAC_VV(v0, q2, q1, VECTOR_UNMASKED); VMV_V_V(v1, q0); VFMACC_VV(v1, q2, q1, VECTOR_UNMASKED); @@ -887,6 +1027,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFMSAC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -899,6 +1042,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFNMSAC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -911,6 +1057,9 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q0); VFNMACC_VV(v0, q2, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -923,6 +1072,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFMACC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -935,8 +1086,11 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); + v1 = fpu_get_scratch(dyn); VFMACC_VV(v0, q0, q2, VECTOR_UNMASKED); VMV_V_V(v1, q1); VFMSAC_VV(v1, q0, q2, VECTOR_UNMASKED); @@ -952,8 +1106,11 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); + v1 = fpu_get_scratch(dyn); VFMSAC_VV(v0, q0, q2, VECTOR_UNMASKED); VMV_V_V(v1, q1); VFMACC_VV(v1, q0, q2, VECTOR_UNMASKED); @@ -969,6 +1126,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFMSAC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -981,6 +1140,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFNMSAC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -993,6 +1154,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q1); VFNMACC_VV(v0, q0, q2, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -1004,10 +1167,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETVY_vector(q0, sew); GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); - VFMACC_VV(v0, q0, q1, VECTOR_UNMASKED); - PUTGY_vector(v0, sew); + VFMACC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0xB6: INST_NAME("VFMADDSUB231PS/D Gx, Vx, Ex"); @@ -1017,8 +1178,11 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q2); + v1 = fpu_get_scratch(dyn); VFMACC_VV(v0, q0, q1, VECTOR_UNMASKED); VMV_V_V(v1, q2); VFMSAC_VV(v1, q0, q1, VECTOR_UNMASKED); @@ -1034,8 +1198,11 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); - v1 = fpu_get_scratch(dyn); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VEC_SRC_KEEP(q2, v0); VMV_V_V(v0, q2); + v1 = fpu_get_scratch(dyn); VFMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); VMV_V_V(v1, q2); VFMACC_VV(v1, q0, q1, VECTOR_UNMASKED); @@ -1051,6 +1218,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); VMV_V_V(v0, q2); VFMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -1063,6 +1232,8 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); VMV_V_V(v0, q2); VFNMSAC_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); @@ -1075,17 +1246,95 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q1, 0, sew); GETGY_vector(q2, sew); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); VMV_V_V(v0, q2); VFNMACC_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, sew); break; case 0xDC: + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESENC Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 != q0) { + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + VMV_V_V(v0, q0); + } + VAESEM_VV(v0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0xDD: - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); - return 0; + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESENCLAST Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 != q0) { + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + VMV_V_V(v0, q0); + } + VAESEF_VV(v0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; + case 0xDE: + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESDEC Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + if (v0 != q0) VMV_V_V(v0, q0); + v1 = fpu_get_scratch(dyn); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VAESDF_VV(v0, v1); + MOV32w(x4, 0x63636363); + VMV_V_X(v1, x4); + VAESDM_VV(v1, v0); + VXOR_VV(v0, v1, q1, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW32); + break; + case 0xDF: + if (!cpuext.zvkned) { + BARRIER(BARRIER_FLOAT); + return 0; + } + INST_NAME("VAESDECLAST Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + if (v0 != q0) { + if (v0 == q1) { + q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q1); + q1 = q2; + } + VMV_V_V(v0, q0); + } + VAESDF_VV(v0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0x13: if (!cpuext.zvfh) { - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); return 0; } INST_NAME("VCVTPH2PS Gx, Ex"); @@ -1133,13 +1382,13 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint INST_NAME("VFNMADD213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1150,26 +1399,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q1); - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); // v0 = -Ex - VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q2, VECTOR_MASKED); // v0[0] = Vx*Gx - Ex - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); // v0[0] = -(Vx*Gx) + Ex - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMSAC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xB9: INST_NAME("VFMADD231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1180,22 +1427,21 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q1, VECTOR_MASKED); // v0[0] = Vx*Ex + Gx - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMACC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0x99: INST_NAME("VFMADD132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1206,22 +1452,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VECTOR_LOAD_VMASK(1, x4, 1); - VFMADD_VV(v0, q0, q1, VECTOR_MASKED); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMACC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0x9B: INST_NAME("VFMSUB132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1232,22 +1480,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VECTOR_LOAD_VMASK(1, x4, 1); - VFMSUB_VV(v0, q0, q1, VECTOR_MASKED); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMSAC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0x9D: INST_NAME("VFNMADD132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1258,23 +1508,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VECTOR_LOAD_VMASK(1, x4, 1); - VFNMSUB_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMSAC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0x9F: INST_NAME("VFNMSUB132Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1285,22 +1536,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VECTOR_LOAD_VMASK(1, x4, 1); - VFNMADD_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q0); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMACC_VV(q4, q2, q1, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xA9: INST_NAME("VFMADD213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1311,23 +1564,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q1); - VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q2, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMACC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xAB: INST_NAME("VFMSUB213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1338,24 +1592,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q1); - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q2, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMSAC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xAF: INST_NAME("VFNMSUB213Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1366,24 +1620,24 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VMV_V_V(v0, q2); - VECTOR_LOAD_VMASK(1, x4, 1); - VFNMADD_VV(v0, q1, q0, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + q4 = fpu_get_scratch(dyn); + VMV_V_V(q4, q1); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMACC_VV(q4, q0, q2, VECTOR_UNMASKED); + VMV_V_V(q2, q4); + PUTGY_vector(q2, sew); break; case 0xBB: INST_NAME("VFMSUB231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1394,24 +1648,21 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VFSGNJN_VV(v0, v0, v0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFMSAC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0xBD: INST_NAME("VFNMADD231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1422,23 +1673,21 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VFSGNJN_VV(q0, q0, q0, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1, x4, 1); - VFMACC_VV(v0, q0, q1, VECTOR_MASKED); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMSAC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); break; case 0xBF: INST_NAME("VFNMSUB231Sx Gx, Vx, Ex"); nextop = F8; sew = rex.w ? VECTOR_SEW64 : VECTOR_SEW32; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, sew); GETGY_vector(q2, sew); - GETGY_empty_vector(v0); - VMV_V_V(v0, q2); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, sew); + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, sew); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); @@ -1449,10 +1698,38 @@ uintptr_t dynarec64_AVX_66_0F38_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint FLW(q1, ed, fixedaddress); VFMV_S_F(q1, q1); } - VECTOR_LOAD_VMASK(1, x4, 1); - VFNMACC_VV(v0, q0, q1, VECTOR_MASKED); - VMERGE_VVM(v0, q2, v0); - PUTGY_vector(v0, sew); + SET_SCALAR_FP_WIDTH(x1, sew); + VFNMACC_VV(q2, q0, q1, VECTOR_UNMASKED); + PUTGY_vector(q2, sew); + break; + case 0xF7: + INST_NAME("SHLX Gd, Ed, Vd"); + nextop = F8; + GETGDd; + GETED(0); + GETVD; + SLLxw(gd, ed, vd); + break; + case 0x41: + if (vex.l || cpuext.xtheadvector) return 0; + INST_NAME("VPHMINPOSUW Gx, Ex"); + nextop = F8; + GETEY_vector(q0, 0, VECTOR_SEW16); + GETGY_empty_vector(v0); + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + VMV_V_I(q2, -1); + VREDMINU_VS(q1, q0, q2, VECTOR_UNMASKED); + VMV_X_S(x4, q1); + ZEXTH(x4, x4); + VMSEQ_VX(VMASK, q0, x4, VECTOR_UNMASKED); + VFIRST_M(x5, VMASK, VECTOR_UNMASKED); + SLLI(x5, x5, 16); + OR(x4, x4, x5); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMV_S_X(v0, x4); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); break; default: DEFAULT_VECTOR; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c index 2eb590fdb..d8799e5e9 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c @@ -354,15 +354,15 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i MARK; FLD(d0, x1, 0); FEQD(x4, d0, d0); - BNEZ(x4, BOX64ENV(dynarec_fastnan) ? 8 : (7 * 4)); + BNEZ_MARK3(x4); if (!BOX64ENV(dynarec_fastnan)) { FMVXD(x3, d0); - ADDI(x4, xZR, 1); - SLLI(x4, x4, 51); + MOV64x(x4, 1ULL << 51); OR(x3, x3, x4); FMVDX(d0, x3); } B_MARK2_nocond; + MARK3; FABSD(v1, d0); FLTD(x4, v1, d1); BNEZ(x4, 8); @@ -946,7 +946,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x42: INST_NAME("VMPSADBW Gx, Vx, Ex, Ib"); nextop = F8; - GETEX(x2, 1, vex.l ? 28 : 12); + GETEX(x2, 1, 22); GETVX(); GETVY(); GETGX(); @@ -1259,6 +1259,8 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i break; case 0x61: INST_NAME("VPCMPESTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); nextop = F8; if (vex.l) { DEFAULT; @@ -1345,6 +1347,8 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i break; case 0x63: INST_NAME("VPCMPISTRI Gx, Ex, Ib"); + MARKREGs(xRAX); + MARKREGs(xRDX); nextop = F8; if (vex.l) { DEFAULT; diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c index 599f4b07b..a488ab6d2 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a_vector.c @@ -59,16 +59,16 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q0, 1, VECTOR_SEW64); GETGY_empty_vector(v0); u8 = F8; - q2 = fpu_get_scratch(dyn); + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch_lmul(dyn, vex.l ? VECTOR_LMUL1 : VECTOR_LMUL2); { uint64_t iota = (u8 & 3) | (((u8 >> 2) & 3) << 16); iota |= ((uint64_t)((u8 >> 4) & 3)) << 32; iota |= ((uint64_t)((u8 >> 6) & 3)) << 48; vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, vex.l ? 2 : 1); - VECTOR_SPLAT_IMM(q2, iota, x4); + VECTOR_SPLAT_IMM_S(q2, iota, x4, x3); } if (v0 == q0 || v0 == q2) { - q1 = fpu_get_scratch(dyn); VRGATHEREI16_VV(q1, q0, q2, VECTOR_UNMASKED); VMV_V_V(v0, q1); } else { @@ -79,9 +79,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x02: INST_NAME("VPBLENDD Gx, Vx, Ex, Imm8"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 1); u8 = F8; VECTOR_LOAD_VMASK(vex.l ? u8 : (u8 & 0xf), x4, vex.l ? 2 : 1); q2 = fpu_get_scratch(dyn); @@ -94,16 +92,21 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q0, 1, VECTOR_SEW32); GETGY_empty_vector(v0); u8 = F8; - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - for (int i = 0; i < (4 << vex.l); ++i) { - int lane = i & ~3; - int selector = lane + ((u8 >> ((i & 3) * 2)) & 3); - MOV32w(x4, selector); - q1 = fpu_get_scratch(dyn); - VRGATHER_VX(q1, q0, x4, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v0, q1); + VEC_SRC_KEEP(q0, v0); + q1 = fpu_get_scratch(dyn); + MOV64xs(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48), x3); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + if (vex.l) { + VMV_V_X(q1, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VOR_VI(q1, q1, 4, VECTOR_MASKED); + } else { + VMV_S_X(q1, x4); } + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); + VRGATHEREI16_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x05: @@ -112,63 +115,52 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint GETEY_vector(q0, 1, VECTOR_SEW64); GETGY_empty_vector(v0); u8 = F8; - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - for (int i = 0; i < (2 << vex.l); ++i) { - int lane = i & ~1; - int selector = lane + ((u8 >> i) & 1); - MOV32w(x4, selector); - q1 = fpu_get_scratch(dyn); - VRGATHER_VX(q1, q0, x4, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(1 << i, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v0, q1); - } + VEC_SRC_KEEP(q0, v0); + q1 = fpu_get_scratch(dyn); + MOV64x(x4, (uint64_t)(u8 & 1) | ((uint64_t)((u8 >> 1) & 1) << 16) | ((uint64_t)(((u8 >> 2) & 1) + 2) << 32) | ((uint64_t)(((u8 >> 3) & 1) + 2) << 48)); + MOV64xs(x4, (uint64_t)(u8 & 1) | ((uint64_t)((u8 >> 1) & 1) << 16) | ((uint64_t)(((u8 >> 2) & 1) + 2) << 32) | ((uint64_t)(((u8 >> 3) & 1) + 2) << 48), x3); + VMV_S_X(q1, x4); + VRGATHEREI16_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x06: if (!vex.l) return 0; INST_NAME("VPERM2F128 Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW64, 1); u8 = F8; - q2 = fpu_get_scratch(dyn); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - for (int i = 0; i < 2; ++i) { - int control = i ? (u8 >> 4) : u8; - int source = (control >> 1) & 1; - int index = control & 1; - int zero = control & 8; + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VMV_V_V(v0, q0); + for (int j = 0; j < 2; ++j) { + int control = j ? (u8 >> 4) & 3 : u8 & 3; + int zero = j ? (u8 & 0x80) : (u8 & 0x08); + int mask = j ? 0xc : 0x3; if (zero) { - VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); - } else if (source) { - if (index) - VSLIDEDOWN_VI(q2, q1, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q1); - } else { - if (index) - VSLIDEDOWN_VI(q2, q0, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q0); - } - if (i) { - VSLIDEUP_VI(q1, q2, 16, VECTOR_UNMASKED); - q2 = q1; + VECTOR_LOAD_VMASK(mask, x4, 2); + VXOR_VV(v0, v0, v0, VECTOR_MASKED); + } else if (control != j) { + int src = (control & 2) ? q1 : q0; + VECTOR_LOAD_VMASK(mask, x4, 2); + if (((j == 0) && ((control & 1) == 0)) || ((j == 1) && ((control & 1) == 1))) { + VMERGE_VVM(v0, v0, src); + } else { + q2 = fpu_get_scratch(dyn); + if (j) + VSLIDEUP_VI(q2, src, 2, VECTOR_UNMASKED); + else + VSLIDEDOWN_VI(q2, src, 2, VECTOR_UNMASKED); + VMERGE_VVM(v0, v0, q2); + } } - VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); - VMERGE_VVM(v0, v0, q2); } - PUTGY_vector(v0, VECTOR_SEW8); + PUTGY_vector(v0, VECTOR_SEW64); break; case 0x0E: INST_NAME("VPBLENDW Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW16, 1); u8 = F8; - VMV_V_V(v0, q0); VECTOR_LOAD_VMASK(u8 | (vex.l ? (u8 << 8) : 0), x4, vex.l ? 2 : 1); VMERGE_VVM(v0, q0, q1); PUTGY_vector(v0, VECTOR_SEW16); @@ -177,37 +169,28 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VINSERTF128 Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); + GETVY_vector(q0, VECTOR_SEW64); q1 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); - avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW8); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW64); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - VLE8_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); } u8 = F8; - if (!(u8 & 1)) - v1 = fpu_get_scratch(dyn); - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - sse_forget_reg_vector(dyn, ninst, x1, gd); - ADDI(x1, xEmu, offsetof(x64emu_t, xmm[gd])); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + GETGY_empty_vector(v0); + VMV_V_V(v0, q0); if (u8 & 1) { - VSE8_V(q0, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); - ADDI(x1, xEmu, offsetof(x64emu_t, ymm[gd])); - VSE8_V(q1, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); + VSLIDEUP_VI_SAFE(v0, q1, 2, VECTOR_UNMASKED); } else { - VSE8_V(q1, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); - VSLIDEDOWN_VI(v1, q0, 16, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - ADDI(x1, xEmu, offsetof(x64emu_t, ymm[gd])); - VSE8_V(v1, x1, VECTOR_UNMASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_V(v0, q1); } - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); + PUTGY_vector(v0, VECTOR_SEW64); break; case 0x19: if (!vex.l) return 0; @@ -259,7 +242,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (u8 & 1) { v1 = fpu_get_scratch(dyn); VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); - VSLIDEUP_VI(v1, q1, 2, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v1, q1, 2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0b1100, x4, 2); VMERGE_VVM(v0, v0, v1); } else { @@ -299,19 +282,15 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x42: INST_NAME("VMPSADBW Gx, Vx, Ex, Ib"); nextop = F8; - mmx_purgecache(dyn, ninst, 0, x1); - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); u8 = F8; - q2 = fpu_get_scratch(dyn); int q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); int q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - int q5 = fpu_get_scratch(dyn); - int q6 = fpu_get_scratch(dyn); - int q7 = fpu_get_scratch(dyn); - int q8 = fpu_get_scratch(dyn); - int q9 = fpu_get_scratch(dyn); + int q2 = fpu_borrow_reg(dyn, ninst, x1, x2, 8); + int q5 = fpu_borrow_reg(dyn, ninst, x1, x2, 9); + int q6 = fpu_borrow_reg(dyn, ninst, x1, x2, 10); + int q7 = fpu_borrow_reg(dyn, ninst, x1, x2, 11); + int q8 = fpu_borrow_reg(dyn, ninst, x1, x2, 12); for (int pass = 0; pass < (vex.l ? 2 : 1); ++pass) { vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); @@ -333,8 +312,8 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (off5) VADD_VI(q5, q5, off5, VECTOR_UNMASKED); if (off6) VADD_VI(q6, q6, off6, VECTOR_UNMASKED); - VRGATHER_VV(q3, q7, q5, VECTOR_UNMASKED); - VRGATHER_VV(q4, q8, q6, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(q3, q7, q5, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(q4, q8, q6, VECTOR_UNMASKED); VMAXU_VV(q7, q3, q4, VECTOR_UNMASKED); VMINU_VV(q4, q3, q4, VECTOR_UNMASKED); VSUB_VV(q7, q7, q4, VECTOR_UNMASKED); @@ -358,7 +337,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMV_V_V(v0, q2); if (vex.l) { avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); - VSLIDEUP_VI(v0, q3, 8, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q3, 8, VECTOR_UNMASKED); } PUTGY_vector(v0, VECTOR_SEW16); break; @@ -366,38 +345,34 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (!vex.l) return 0; INST_NAME("VPERM2I128 Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW64, 1); u8 = F8; - q2 = fpu_get_scratch(dyn); - VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - for (int i = 0; i < 2; ++i) { - int control = i ? (u8 >> 4) : u8; - int source = (control >> 1) & 1; - int index = control & 1; - int zero = control & 8; + VEC_SRC_KEEP(q0, v0); + VEC_SRC_KEEP(q1, v0); + VMV_V_V(v0, q0); + for (int j = 0; j < 2; ++j) { + int control = j ? (u8 >> 4) & 3 : u8 & 3; + int zero = j ? (u8 & 0x80) : (u8 & 0x08); + int mask = j ? 0xc : 0x3; if (zero) { - VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); - } else if (source) { - if (index) - VSLIDEDOWN_VI(q2, q1, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q1); - } else { - if (index) - VSLIDEDOWN_VI(q2, q0, 16, VECTOR_UNMASKED); - else - VMV_V_V(q2, q0); - } - if (i) { - VSLIDEUP_VI(q1, q2, 16, VECTOR_UNMASKED); - q2 = q1; + VECTOR_LOAD_VMASK(mask, x4, 2); + VXOR_VV(v0, v0, v0, VECTOR_MASKED); + } else if (control != j) { + int src = (control & 2) ? q1 : q0; + VECTOR_LOAD_VMASK(mask, x4, 2); + if (((j == 0) && ((control & 1) == 0)) || ((j == 1) && ((control & 1) == 1))) { + VMERGE_VVM(v0, v0, src); + } else { + q2 = fpu_get_scratch(dyn); + if (j) + VSLIDEUP_VI(q2, src, 2, VECTOR_UNMASKED); + else + VSLIDEDOWN_VI(q2, src, 2, VECTOR_UNMASKED); + VMERGE_VVM(v0, v0, q2); + } } - VECTOR_LOAD_VMASK(i ? 0xffff0000 : 0xffff, x4, 2); - VMERGE_VVM(v0, v0, q2); } - PUTGY_vector(v0, VECTOR_SEW8); + PUTGY_vector(v0, VECTOR_SEW64); break; case 0x08: INST_NAME("VROUNDPS Gx, Ex, Ib"); @@ -621,9 +596,7 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint case 0x0C: INST_NAME("VBLENDPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 1); u8 = F8; VECTOR_LOAD_VMASK(vex.l ? u8 : (u8 & 0xf), x4, vex.l ? 2 : 1); q2 = fpu_get_scratch(dyn); @@ -653,6 +626,65 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SMWRITE2(); } break; + case 0x15: + INST_NAME("VPEXTRW Ew, Gx, Ib"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, ((nextop & 0x38) >> 3) + (rex.r << 3), 16, VECTOR_SEW16); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + } + u8 = F8; + q1 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q1, q0, u8 & 7, VECTOR_UNMASKED); + VMV_X_S(x4, q1); + if (MODREG) { + ZEXTH(ed, x4); + } else { + SH(x4, ed, fixedaddress); + SMWRITE2(); + } + break; + case 0x16: + if (rex.w) { + INST_NAME("VPEXTRQ Ed, Gx, Ib"); + } else { + INST_NAME("VPEXTRD Ed, Gx, Ib"); + } + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, ((nextop & 0x38) >> 3) + (rex.r << 3), 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + SET_AVX_VECTOR_WIDTH(x1, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + } + u8 = F8; + q1 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q1, q0, rex.w ? (u8 & 1) : (u8 & 3), VECTOR_UNMASKED); + VMV_X_S(x4, q1); + if (MODREG) { + if (rex.w) { + MV(ed, x4); + } else { + MV(ed, x4); + ZEROUP(ed); + } + } else { + if (rex.w) { + SD(x4, ed, fixedaddress); + } else { + SW(x4, ed, fixedaddress); + } + SMWRITE2(); + } + break; case 0x17: if (rex.w) return 0; INST_NAME("VEXTRACTPS Em, Gx, Ib"); @@ -682,9 +714,9 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint if (rex.w) return 0; INST_NAME("VPINSRB Gx, Vx, Ed, Ib"); nextop = F8; - GETGY_empty_vector(v0); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW8); + GETGY_empty_vector(v0); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); ANDI(x5, ed, 0xFF); @@ -702,10 +734,46 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint VMERGE_VVM(q2, q0, q1); avx_store_reg_vector(dyn, ninst, x1, q2, gd, 16, VECTOR_SEW8); break; + case 0x22: + if (rex.w) { + INST_NAME("VPINSRQ Gx, Vx, ED, Ib"); + } else { + INST_NAME("VPINSRD Gx, Vx, ED, Ib"); + } + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); + if (rex.w) { + LD(x5, ed, fixedaddress); + } else { + LWU(x5, ed, fixedaddress); + } + ed = x5; + } + u8 = F8; + if (rex.w) { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VECTOR_LOAD_VMASK(1 << (u8 & 1), x4, 1); + } else { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VECTOR_LOAD_VMASK(1 << (u8 & 3), x4, 1); + } + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + VMV_V_X(q1, ed); + VMERGE_VVM(q2, q0, q1); + avx_store_reg_vector(dyn, ninst, x1, q2, gd, 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + break; case 0x21: INST_NAME("VINSERTPS Gx, Vx, Ex, Ib"); nextop = F8; - GETGY_empty_vector(v0); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); @@ -716,33 +784,39 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 1); } + GETGY_empty_vector(v0); u8 = F8; q2 = fpu_get_scratch(dyn); + VMV_V_V(q2, q0); if (MODREG) { - VSLIDEDOWN_VI(q2, q1, (u8 >> 6) & 3, VECTOR_UNMASKED); - VMV_X_S(x5, q2); + q3 = fpu_get_scratch(dyn); + int count_s = (u8 >> 6) & 3; + int count_d = (u8 >> 4) & 3; + if (count_s > count_d) { + VSLIDEDOWN_VI(q3, q1, count_s - count_d, VECTOR_UNMASKED); + } else if (count_s < count_d) { + VSLIDEUP_VI_SAFE(q3, q1, count_d - count_s, VECTOR_UNMASKED); + } else { + q3 = q1; + } } else { + q3 = fpu_get_scratch(dyn); LWU(x5, ed, fixedaddress); + VMV_V_X(q3, x5); } + VECTOR_LOAD_VMASK(1 << ((u8 >> 4) & 3), x4, 1); + VMERGE_VVM(q2, q2, q3); // zero out the dwords selected by imm8[3:0] - VECTOR_LOAD_VMASK(u8 & 0xf, x4, 1); - q3 = fpu_get_scratch(dyn); - q4 = fpu_get_scratch(dyn); - VXOR_VV(q3, q3, q3, VECTOR_UNMASKED); - VMERGE_VVM(q4, q0, q3); - if (!(u8 & (1 << ((u8 >> 4) & 3)))) { - VECTOR_LOAD_VMASK(1 << ((u8 >> 4) & 3), x4, 1); - VMV_V_X(q3, x5); - VMERGE_VVM(q4, q4, q3); + if (u8 & 0xf) { + VECTOR_LOAD_VMASK(u8 & 0xf, x4, 1); + VXOR_VV(q2, q2, q2, VECTOR_MASKED); } - PUTGY_vector(q4, VECTOR_SEW32); + PUTGY_vector(q2, VECTOR_SEW32); break; case 0x40: { INST_NAME("VDPPS Gx, Vx, Ex, Ib"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW32, 1); u8 = F8; SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); q3 = fpu_get_scratch(dyn); @@ -775,6 +849,20 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint PUTGY_vector(q3, VECTOR_SEW32); break; } + case 0x4A: + INST_NAME("VBLENDVPS Gx, Vx, Ex, Vx2"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW32); + GETEY_vector(q1, 1, VECTOR_SEW32); + u8 = F8; + q2 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q2, (u8 >> 4) & 0xf, 16 << vex.l, VECTOR_SEW32); + GETGY_empty_vector(v0); + VMSLT_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VMERGE_VVM(v0, q0, q1); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0x4C: if (rex.w) return 0; INST_NAME("VPBLENDVB Gx, Vx, Ex, Vx2"); @@ -782,10 +870,10 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW8); GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); u8 = F8; q2 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q2, (u8 >> 4) & 0xf, 16 << vex.l, VECTOR_SEW8); + GETGY_empty_vector(v0); VMSLT_VX(VMASK, q2, xZR, VECTOR_UNMASKED); VMERGE_VVM(v0, q0, q1); PUTGY_vector(v0, VECTOR_SEW8); @@ -796,14 +884,57 @@ uintptr_t dynarec64_AVX_66_0F3A_vector(dynarec_rv64_t* dyn, uintptr_t addr, uint q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW64); GETEY_vector(q1, 1, VECTOR_SEW64); - GETGY_empty_vector(v0); u8 = F8; q2 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q2, (u8 >> 4) & 0xf, 16 << vex.l, VECTOR_SEW64); + GETGY_empty_vector(v0); VMSLT_VX(VMASK, q2, xZR, VECTOR_UNMASKED); VMERGE_VVM(v0, q0, q1); PUTGY_vector(v0, VECTOR_SEW64); break; + case 0x0D: + INST_NAME("VBLENDPD Gx, Vx, Ex, Ib"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW64, 1); + u8 = F8; + VECTOR_LOAD_VMASK(vex.l ? (u8 & 0xf) : (u8 & 0x3), x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q0, q1); + PUTGY_vector(v0, VECTOR_SEW64); + break; + case 0x0F: + INST_NAME("VPALIGNR Gx, Vx, Ex, Ib"); + nextop = F8; + GETGY_empty_VYEY_vector_D(v0, q0, q1, VECTOR_SEW8, 1); + u8 = F8; + if (u8 > 31) { + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } else { + q2 = fpu_get_scratch(dyn); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 4); + VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VMV_V_V(q2, q1); + VSLIDEUP_VI_SAFE(q2, q0, 16, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 4); + VXOR_VV(q3, q3, q3, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VMV_V_V(q3, q0); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 1); + VSLIDEDOWN_VI(q3, q1, 16, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q4, q3, u8, VECTOR_UNMASKED); + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 1); + VSLIDEDOWN_VI(v0, q2, u8, VECTOR_UNMASKED); + if (vex.l) { + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VSLIDEUP_VI_SAFE(v0, q4, 16, VECTOR_UNMASKED); + } + } + PUTGY_vector(v0, VECTOR_SEW8); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c index 929ed966d..b0f4e68c5 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_66_0f_vector.c @@ -29,7 +29,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint8_t gd, ed; uint8_t wback; int v0, v1, v2; - int q0, q1, q2, d0, d1; + int q0, q1, q2, q3, q4, q5, d0, d1; + int j64; uint64_t selectors; int64_t fixedaddress; rex_t rex = vex.rex; @@ -40,6 +41,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MAYUSE(q2); MAYUSE(d0); MAYUSE(d1); + MAYUSE(j64); switch (opcode) { case 0x10: @@ -67,17 +69,16 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x12: INST_NAME("VMOVLPD Gx, Vx, Ex"); nextop = F8; + if (MODREG) return 0; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); GETGY_empty_vector(v0); - avx_load_reg_vector(dyn, ninst, x1, v0, vex.v, 16, VECTOR_SEW64); - if (MODREG) { - return 0; - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - LD(x2, ed, fixedaddress); - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); - VMV_S_X(v0, x2); - } + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + LD(x2, ed, fixedaddress); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_V(v0, q0); + VMV_S_X(v0, x2); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x13: @@ -93,16 +94,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x14: INST_NAME("VUNPCKLPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 2, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0x0a, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW64); @@ -110,17 +109,15 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x15: INST_NAME("VUNPCKHPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 2, VECTOR_UNMASKED); VADD_VI(q2, q2, 1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0x0a, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW64); @@ -137,14 +134,13 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); - if (fixedaddress) { ADDI(x4, ed, fixedaddress); ed = x4; fixedaddress = 0; } - vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 0.5); - VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + LD(x4, ed, fixedaddress); + VMV_S_X(q1, x4); } GETGY_empty_vector(v0); avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VMV_V_V(v0, q0); - VSLIDEUP_VI(v0, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x17: @@ -192,14 +188,59 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SMWRITE2(); break; case 0x2E: - return 0; case 0x2F: - return 0; + if (opcode == 0x2F) { + INST_NAME("VCOMISD Gx, Ex"); + } else { + INST_NAME("VUCOMISD Gx, Ex"); + } + SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); + SET_DFNONE(); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW64); + d0 = fpu_get_scratch(dyn); + VFMV_F_S(d0, q0); + d1 = fpu_get_scratch(dyn); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q1 = VREG(ed); + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, VECTOR_SEW64); + VFMV_F_S(d1, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + FLD(d1, ed, fixedaddress); + } + CLEAR_FLAGS(); + IFX (X_ZF | X_PF | X_CF) { + FEQD(x3, d0, d0); + FEQD(x2, d1, d1); + AND(x2, x2, x3); + BNE_MARK(x2, xZR); + ORI(xFlags, xFlags, (1 << F_ZF) | (1 << F_PF) | (1 << F_CF)); + B_NEXT_nocond; + } + MARK; + IFX (X_CF) { + FLTD(x2, d0, d1); + BEQ_MARK2(x2, xZR); + ORI(xFlags, xFlags, 1 << F_CF); + B_NEXT_nocond; + } + MARK2; + IFX (X_ZF) { + FEQD(x2, d0, d1); + CBZ_NEXT(x2); + ORI(xFlags, xFlags, 1 << F_ZF); + } + break; case 0x50: INST_NAME("VMOVMSKPD Gd, Ex"); nextop = F8; GETEY_vector(q0, 0, VECTOR_SEW64); - GETGD; + GETGDd; VMSLT_VX(VMASK, q0, xZR, VECTOR_UNMASKED); VMV_X_S(gd, VMASK); ANDI(gd, gd, vex.l ? 0x0f : 0x03); @@ -216,18 +257,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x54: INST_NAME("VANDPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x55: INST_NAME("VANDNPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); VAND_VV(v0, v0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -235,18 +272,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x56: INST_NAME("VORPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x57: INST_NAME("VXORPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -254,9 +287,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -264,9 +295,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -286,6 +315,9 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VLE64_V(d0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); } v0 = fpu_get_scratch(dyn); + if (!vex.l && !cpuext.xtheadvector) { + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, vex.l ? 1 : 0.5); u8 = sse_setround(dyn, ninst, x6, x4); VFNCVT_F_F_W(v0, d0, VECTOR_UNMASKED); @@ -306,73 +338,59 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x5D: INST_NAME("VMINPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); - VMV_V_V(v0, q0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x5F: INST_NAME("VMAXPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); - VMV_V_V(v0, q0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); - VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); - VADD_VX(v0, q1, xZR, VECTOR_MASKED); + VMERGE_VVM(v0, q1, q0); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x60: INST_NAME("VPUNPCKLBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); - v1 = fpu_get_scratch(dyn); - v2 = fpu_get_scratch(dyn); - VID_V(q2, VECTOR_UNMASKED); - MOV32w(x4, 16); - VAND_VX(v1, q2, x4, VECTOR_UNMASKED); - VAND_VI(q2, q2, 15, VECTOR_UNMASKED); - VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); - VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(0xaaaaaaaa, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v1, v2); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + { + int w2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, vex.l ? 2 : 1); + VMV_V_I(VMASK, 0b0101); + VCOMPRESS_VM(q2, q0, VMASK); + VCOMPRESS_VM(q3, q1, VMASK); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, vex.l ? 2 : 1); + VWADDU_VX(q4, q2, xZR, VECTOR_UNMASKED); + VWADDU_VX(w2, q3, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX(q2, w2, xZR, VECTOR_UNMASKED); + VOR_VV(v0, q2, q4, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x61: INST_NAME("VPUNPCKLWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -381,8 +399,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VAND_VI(q2, q2, 7, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaaaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW16); @@ -390,9 +408,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x62: INST_NAME("VPUNPCKLDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -401,55 +417,68 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VAND_VI(q2, q2, 3, VECTOR_UNMASKED); VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x63: - if (vex.l) return 0; INST_NAME("VPACKSSWB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); - VMV_V_V(q2, q0); - VSLIDEUP_VI(q2, q1, 8, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMV_V_V(q2, q0); + if (q1 & 1) { + VMV_V_V(q3, q1); + q1 = q3; + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 4); + VSLIDEUP_VI_SAFE(q2, q1, 16, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); + VNCLIP_WI(q4, q2, 0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + MOV64x(x4, 0x0003000100020000ULL); + VMV_S_X(q3, x4); + VRGATHEREI16_VV(v0, q4, q3, VECTOR_UNMASKED); + } else { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMV_V_V(q2, q0); + VSLIDEUP_VI_SAFE(q2, q1, 8, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); + VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x68: INST_NAME("VPUNPCKHBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); - v1 = fpu_get_scratch(dyn); - v2 = fpu_get_scratch(dyn); - VID_V(q2, VECTOR_UNMASKED); - MOV32w(x4, 16); - VAND_VX(v1, q2, x4, VECTOR_UNMASKED); - VAND_VI(q2, q2, 15, VECTOR_UNMASKED); - VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); - VADD_VI(q2, q2, 8, VECTOR_UNMASKED); - VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); - VECTOR_LOAD_VMASK(0xaaaaaaaa, x4, vex.l ? 2 : 1); - VMERGE_VVM(v0, v1, v2); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + { + int w2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, vex.l ? 2 : 1); + VMV_V_I(VMASK, 0b1010); + VCOMPRESS_VM(q2, q0, VMASK); + VCOMPRESS_VM(q3, q1, VMASK); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW8, VECTOR_LMUL1, vex.l ? 2 : 1); + VWADDU_VX(q4, q2, xZR, VECTOR_UNMASKED); + VWADDU_VX(w2, q3, xZR, VECTOR_UNMASKED); + VSLIDE1UP_VX(q2, w2, xZR, VECTOR_UNMASKED); + VOR_VV(v0, q2, q4, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x69: INST_NAME("VPUNPCKHWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -459,8 +488,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VI(q2, q2, 4, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaaaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW16); @@ -468,9 +497,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x6A: INST_NAME("VPUNPCKHDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch(dyn); v1 = fpu_get_scratch(dyn); v2 = fpu_get_scratch(dyn); @@ -480,68 +507,114 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VSRL_VI(q2, q2, 1, VECTOR_UNMASKED); VADD_VI(q2, q2, 2, VECTOR_UNMASKED); VADD_VV(q2, q2, v1, VECTOR_UNMASKED); - VRGATHER_VV(v1, q0, q2, VECTOR_UNMASKED); - VRGATHER_VV(v2, q1, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v1, q0, q2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v2, q1, q2, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(0xaa, x4, vex.l ? 2 : 1); VMERGE_VVM(v0, v1, v2); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x6B: - if (vex.l) return 0; INST_NAME("VPACKSSDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); - VMV_V_V(q2, q0); - VSLIDEUP_VI(q2, q1, 4, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16); - VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); + VMV_V_V(q2, q0); + if (q1 & 1) { + VMV_V_V(q3, q1); + q1 = q3; + } + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 4); + VSLIDEUP_VI_SAFE(q2, q1, 8, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VNCLIP_WI(q4, q2, 0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + MOV64x(x4, 0x0003000100020000ULL); + VMV_S_X(q3, x4); + VRGATHEREI16_VV(v0, q4, q3, VECTOR_UNMASKED); + } else { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 32); + VMV_V_V(q2, q0); + VSLIDEUP_VI_SAFE(q2, q1, 4, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16); + VNCLIP_WI(v0, q2, 0, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW16); break; case 0x67: - if (vex.l) return 0; INST_NAME("VPACKUSWB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); - VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); - v1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); - VMAX_VX(v1, q1, xZR, VECTOR_UNMASKED); - VSLIDEUP_VI(q2, v1, 8, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); - VNCLIPU_WI(v0, q2, 0, VECTOR_UNMASKED); + if (vex.l) { + q3 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q4 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); + VMAX_VX(q3, q1, xZR, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, 4); + VSLIDEUP_VI_SAFE(q2, q3, 16, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 32); + VNCLIPU_WI(q4, q2, 0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 2); + MOV64x(x4, 0x0003000100020000ULL); + VMV_S_X(q3, x4); + VRGATHEREI16_VV(v0, q4, q3, VECTOR_UNMASKED); + } else { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 32); + VMAX_VX(q2, q0, xZR, VECTOR_UNMASKED); + v1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMAX_VX(v1, q1, xZR, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 8, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); + VNCLIPU_WI(v0, q2, 0, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW8); break; case 0x6C: - if (vex.l) return 0; INST_NAME("VPUNPCKLQDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); - VMV_V_V(v0, q0); - VSLIDEUP_VI(v0, q1, 1, VECTOR_UNMASKED); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); + if (vex.l) { + q2 = fpu_get_scratch(dyn); + VID_V(q2, VECTOR_UNMASKED); + VAND_VI(q2, q2, 1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VMV_V_V(v0, q0); + VSLIDEUP_VI(v0, q1, 1, VECTOR_MASKED); + } else { + VMV_V_V(v0, q0); + VSLIDEUP_VI_SAFE(v0, q1, 1, VECTOR_UNMASKED); + } PUTGY_vector(v0, VECTOR_SEW64); break; case 0x6D: - if (vex.l) return 0; INST_NAME("VPUNPCKHQDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); - q2 = fpu_get_scratch(dyn); - v1 = fpu_get_scratch(dyn); - VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); - VSLIDEDOWN_VI(v1, q1, 1, VECTOR_UNMASKED); - VSLIDEUP_VI(q2, v1, 1, VECTOR_UNMASKED); - VMV_V_V(v0, q2); + if (vex.l) { + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); + q2 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + v2 = fpu_get_scratch(dyn); + VID_V(q2, VECTOR_UNMASKED); + VAND_VI(q2, q2, 1, VECTOR_UNMASKED); + VMSNE_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VSLIDEDOWN_VI(v1, q0, 1, VECTOR_UNMASKED); + VSLIDEDOWN_VI(v2, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI(v1, v2, 1, VECTOR_MASKED); + VMV_V_V(v0, v1); + } else { + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); + q2 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); + VSLIDEDOWN_VI(v1, q1, 1, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(q2, v1, 1, VECTOR_UNMASKED); + VMV_V_V(v0, q2); + } PUTGY_vector(v0, VECTOR_SEW64); break; case 0x6E: @@ -567,22 +640,20 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; GETEY_vector(q1, 1, VECTOR_SEW32); GETGY_empty_vector(v0); + VEC_SRC_KEEP(q1, v0); u8 = F8; - q2 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL1); { uint32_t sel_lo = (u8 & 3) | (((u8 >> 2) & 3) << 16); uint32_t sel_hi = ((u8 >> 4) & 3) | (((u8 >> 6) & 3) << 16); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); - MOV32w(x4, sel_hi); - SLLI(x4, x4, 32); - MOV32w(x5, sel_lo); - OR(x4, x4, x5); // x4 = lane0 selector (64-bit,4 halfword indices) + MOV64x(x4, ((uint64_t)sel_hi << 32) | sel_lo); if (vex.l) { int s = fpu_get_scratch(dyn); MOV64x(x5, 0x0004000400040004LL); ADD(x5, x4, x5); // x5 = lane1 selector VMV_S_X(s, x5); // s[0] = lane1 selector - VSLIDE1UP_VX(q2, s, x4, VECTOR_UNMASKED); // q2[0]=x4, q2[1]=s[0] + VSLIDE1UP_VX_SAFE(q2, s, x4, VECTOR_UNMASKED); // q2[0]=x4, q2[1]=s[0] } else { VMV_S_X(q2, x4); } @@ -597,8 +668,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 2: INST_NAME("VPSRLW Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -609,8 +680,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 4: INST_NAME("VPSRAW Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) u8 = 15; VSRA_VI(v0, q1, u8, VECTOR_UNMASKED); @@ -619,8 +690,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 6: INST_NAME("VPSLLW Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW16); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -638,8 +709,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 2: INST_NAME("VPSRLD Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 31) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -650,8 +721,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 4: INST_NAME("VPSRAD Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 31) u8 = 31; VSRA_VI(v0, q1, u8, VECTOR_UNMASKED); @@ -660,8 +731,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 6: INST_NAME("VPSLLD Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW32); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 31) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -679,8 +750,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 2: INST_NAME("VPSRLQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW64); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 63) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -694,8 +765,8 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 3: INST_NAME("VPSRLDQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) { VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -709,16 +780,17 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VADD_VI(q2, q2, u8, VECTOR_UNMASKED); ADDI(x4, xZR, 16 - u8); VMSLTU_VX(VMASK, v1, x4, VECTOR_UNMASKED); + VEC_SRC_KEEP(q1, v0); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q2, VECTOR_MASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_MASKED); } PUTGY_vector(v0, VECTOR_SEW8); break; case 7: INST_NAME("VPSLLDQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW8); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 15) { VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -733,16 +805,17 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VSUB_VX(q2, q2, x4, VECTOR_UNMASKED); ADDI(x4, xZR, u8 - 1); VMSGTU_VX(VMASK, v1, x4, VECTOR_UNMASKED); + VEC_SRC_KEEP(q1, v0); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); - VRGATHER_VV(v0, q1, q2, VECTOR_MASKED); + VRGATHER_VV_SAFE(v0, q1, q2, VECTOR_MASKED); } PUTGY_vector(v0, VECTOR_SEW8); break; case 6: INST_NAME("VPSLLQ Gx, Ex, Ib"); GETEY_vector(q1, 1, VECTOR_SEW64); - GETGY_empty_vector(v0); gd = vex.v; + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); u8 = F8; if (u8 > 63) VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); @@ -760,9 +833,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x64: INST_NAME("VPCMPGTB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -771,9 +842,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x65: INST_NAME("VPCMPGTW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -782,9 +851,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x66: INST_NAME("VPCMPGTD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMSLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -793,17 +860,25 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x6F: INST_NAME("VMOVDQA Gx, Ex"); nextop = F8; - GETEY_vector(v1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); - VMV_V_V(v0, v1); - PUTGY_vector(v0, VECTOR_SEW8); + if (!MODREG) { + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VLE8_V(v0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16 << vex.l, VECTOR_SEW8); + } else { + GETEY_vector(v1, 0, VECTOR_SEW8); + GETGY_empty_vector(v0); + VMV_V_V(v0, v1); + PUTGY_vector(v0, VECTOR_SEW8); + } break; case 0x74: INST_NAME("VPCMPEQB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -812,9 +887,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x75: INST_NAME("VPCMPEQW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -823,9 +896,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x76: INST_NAME("VPCMPEQD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VMSEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); VMERGE_VIM(v0, v0, 0x1f); @@ -846,14 +917,31 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt } break; case 0x7E: - return 0; + INST_NAME(rex.w ? "VMOVQ Ed, Gx" : "VMOVD Ed, Gx"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, ((nextop & 0x38) >> 3) + (rex.r << 3), 16, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + SET_AVX_VECTOR_WIDTH(x1, rex.w ? VECTOR_SEW64 : VECTOR_SEW32); + if (MODREG) { + ed = TO_NAT((nextop & 7) + (rex.b << 3)); + VMV_X_S(ed, q0); + if (!rex.w) ZEROUP(ed); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + VMV_X_S(x4, q0); + if (rex.w) + SD(x4, ed, fixedaddress); + else + SW(x4, ed, fixedaddress); + SMWRITE2(); + } + break; case 0xD0: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDSUBPD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); q2 = fpu_get_scratch(dyn); VID_V(q2, VECTOR_UNMASKED); VAND_VI(q2, q2, 1, VECTOR_UNMASKED); @@ -904,6 +992,32 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VAND_VX(v0, v0, x5, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; + case 0xE1: + INST_NAME("VPSRAW Gx, Vx, Ex"); + nextop = F8; + GETVY_vector(q0, VECTOR_SEW16); + GETEY128_vector(q1, 0, VECTOR_SEW64); + GETGY_empty_vector(v0); + VMV_X_S(x4, q1); + ADDI(x5, xZR, 15); + MINU(x4, x4, x5); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); + VSRA_VX(v0, q0, x4, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW16); + break; + case 0xE2: + INST_NAME("VPSRAD Gx, Vx, Ex"); + nextop = F8; + GETVY_vector(q0, VECTOR_SEW32); + GETEY128_vector(q1, 0, VECTOR_SEW64); + GETGY_empty_vector(v0); + VMV_X_S(x4, q1); + ADDI(x5, xZR, 31); + MINU(x4, x4, x5); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VSRA_VX(v0, q0, x4, VECTOR_UNMASKED); + PUTGY_vector(v0, VECTOR_SEW32); + break; case 0xD6: if (vex.l) return 0; INST_NAME("VMOVQ Ex, Gx"); @@ -912,7 +1026,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (MODREG) { ed = (nextop & 7) + (rex.b << 3); q1 = fpu_get_scratch(dyn); - avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 2); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VXOR_VV(q1, q1, q1, VECTOR_UNMASKED); VECTOR_LOAD_VMASK(1, x4, 1); VMERGE_VVM(q1, q1, q0); @@ -927,27 +1041,21 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD4: INST_NAME("VPADDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xD5: INST_NAME("VPMULLW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xD8: INST_NAME("VPSUBUSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); q2 = fpu_get_scratch(dyn); VMSLTU_VV(VMASK, q0, q1, VECTOR_UNMASKED); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -958,9 +1066,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD9: INST_NAME("VPSUBUSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch(dyn); VMSLTU_VV(VMASK, q0, q1, VECTOR_UNMASKED); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); @@ -971,54 +1077,42 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xDA: INST_NAME("VPMINUB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMINU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xDB: INST_NAME("VPAND Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VAND_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xDC: INST_NAME("VPADDUSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xDD: INST_NAME("VPADDUSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xDE: INST_NAME("VPMAXUB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VMAXU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xDF: INST_NAME("VPANDN Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector_safe(v0, q0, q1, VECTOR_SEW64); VXOR_VI(v0, q0, 0x1f, VECTOR_UNMASKED); VAND_VV(v0, v0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); @@ -1026,9 +1120,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE0: INST_NAME("VPAVGB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); CSRRWI(xZR, 0b00, 0x00A); VAADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); @@ -1036,9 +1128,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE3: INST_NAME("VPAVGW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); CSRRWI(xZR, 0b00, 0x00A); VAADDU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); @@ -1046,18 +1136,14 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE4: INST_NAME("VPMULHUW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMULHU_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xE5: INST_NAME("VPMULHW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMULH_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; @@ -1074,72 +1160,56 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xE8: INST_NAME("VPSUBSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xE9: INST_NAME("VPSUBSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEA: INST_NAME("VPMINSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMIN_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEB: INST_NAME("VPOR Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xEC: INST_NAME("VPADDSB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xED: INST_NAME("VPADDSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEE: INST_NAME("VPMAXSW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VMAX_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xEF: INST_NAME("VPXOR Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VXOR_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; @@ -1187,21 +1257,19 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xF4: INST_NAME("VPMULUDQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); MOV64x(x2, 0xffffffffULL); - VAND_VX(q0, q0, x2, VECTOR_UNMASKED); - VAND_VX(q1, q1, x2, VECTOR_UNMASKED); - VMUL_VV(v0, q0, q1, VECTOR_UNMASKED); + q2 = fpu_get_scratch(dyn); + d0 = fpu_get_scratch(dyn); + VAND_VX(q2, q0, x2, VECTOR_UNMASKED); + VAND_VX(d0, q1, x2, VECTOR_UNMASKED); + VMUL_VV(v0, q2, d0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xF5: INST_NAME("VPMADDWD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); @@ -1214,66 +1282,90 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VADD_VV(v0, d0, d1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; + case 0xF6: + INST_NAME("VPSADBW Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); + q2 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + v1 = fpu_get_scratch(dyn); + v2 = fpu_get_scratch(dyn); + d0 = q2 + 1; // second register of the LMUL2 group, used at VLEN=256 + if (vex.l && cpuext.vlen > 32) d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VMINU_VV(v1, q0, q1, VECTOR_UNMASKED); + VMAXU_VV(v2, q0, q1, VECTOR_UNMASKED); + VSUB_VV(v1, v2, v1, VECTOR_UNMASKED); + VWADDU_VX(q2, v1, xZR, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL2, vex.l ? 4 : 2); + if (vex.l && cpuext.vlen > 32) VSLIDEDOWN_VI(d0, q2, 16, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); + ADDI(x4, xZR, 0xFF); + VMV_S_X(VMASK, x4); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, q2, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, VMASK, VMASK); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, q2, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 4, VECTOR_UNMASKED); + if (vex.l) { + VMNAND_MM(VMASK, VMASK, VMASK); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, d0, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 8, VECTOR_UNMASKED); + VMNAND_MM(VMASK, VMASK, VMASK); + VXOR_VV(v1, v1, v1, VECTOR_UNMASKED); + VREDSUM_VS(v1, d0, v1, VECTOR_MASKED); + VSLIDEUP_VI_SAFE(v0, v1, 12, VECTOR_UNMASKED); + } + PUTGY_vector(v0, VECTOR_SEW16); + break; case 0xF8: INST_NAME("VPSUBB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xF9: INST_NAME("VPSUBW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xFA: INST_NAME("VPSUBD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0xFB: INST_NAME("VPSUBQ Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW64); - GETEY_vector(q1, 0, VECTOR_SEW64); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); VSUB_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0xFC: INST_NAME("VPADDB Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW8); - GETEY_vector(q1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW8); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW8); break; case 0xFD: INST_NAME("VPADDW Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW16); - GETEY_vector(q1, 0, VECTOR_SEW16); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW16); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xFE: INST_NAME("VPADDD Gx, Vx, Ex"); nextop = F8; - GETVY_vector(q0, VECTOR_SEW32); - GETEY_vector(q1, 0, VECTOR_SEW32); - GETGY_empty_vector(v0); + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); VADD_VV(v0, q0, q1, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; @@ -1281,9 +1373,9 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (vex.l) return 0; INST_NAME("VPINSRW Gx, Vx, Ed, Ib"); nextop = F8; - GETGY_empty_vector(v0); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW16); + GETGY_empty_vector(v0); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); ZEXTH(x5, ed); @@ -1306,7 +1398,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt nextop = F8; if (!MODREG) return 0; INST_NAME("VPEXTRW Gd, Ex, Ib"); - GETGD; + GETGDd; q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW16); SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); @@ -1319,7 +1411,7 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0xD7: INST_NAME("VPMOVMSKB Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW8); q0 = fpu_get_scratch(dyn); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16 << vex.l, VECTOR_SEW8); @@ -1340,6 +1432,149 @@ uintptr_t dynarec64_AVX_66_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt ZEXTH(gd, gd); } break; + case 0xC6: + INST_NAME("VSHUFPD Gx, Vx, Ex, Ib"); + nextop = F8; + q0 = fpu_get_scratch(dyn); + q1 = fpu_get_scratch(dyn); + q2 = fpu_get_scratch(dyn); + v2 = fpu_get_scratch(dyn); + v1 = fpu_get_scratch_lmul(dyn, vex.l ? VECTOR_LMUL1 : VECTOR_LMUL2); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16 << vex.l, VECTOR_SEW64); + if (MODREG) { + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16 << vex.l, VECTOR_SEW64); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 1); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VLE64_V(q1, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + } + GETGY_empty_vector(v0); + u8 = F8; + selectors = 0; + for (int i = 0; i < (2 << vex.l); ++i) + selectors |= (uint64_t)((i >> 1) * 2 + ((u8 >> i) & 1)) << (i * 16); + MOV64xs(x4, selectors, x3); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VMV_V_X(v1, x4); + VRGATHEREI16_VV(q2, q0, v1, VECTOR_UNMASKED); + VRGATHEREI16_VV(v2, q1, v1, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(0xa, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q2, v2); + PUTGY_vector(v0, VECTOR_SEW64); + break; + case 0xC2: + INST_NAME("VCMPPD Gx, Vx, Ex, Ib"); + nextop = F8; + GETVY_vector(q0, VECTOR_SEW64); + GETEY_vector(q1, 1, VECTOR_SEW64); + u8 = F8; + GETGY_empty_vector(v0); + q2 = fpu_get_scratch(dyn); + d0 = fpu_get_scratch(dyn); + switch (u8 & 0xf) { + case 0x0: VMFEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; + case 0x1: VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; + case 0x2: VMFLE_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; + case 0x3: + AVX_CMP_ORDERED_MASK(); + VMNAND_MM(VMASK, q2, q2); + break; + case 0x4: + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0x5: + VMFLT_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0x6: + VMFLE_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0x7: + AVX_CMP_ORDERED_MASK(); + VMAND_MM(VMASK, q2, q2); + break; + case 0x8: + AVX_CMP_ORDERED_MASK(); + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, q2, q2); + VMOR_MM(VMASK, VMASK, d0); + break; + case 0x9: + VMFLE_VV(d0, q1, q0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0xa: + VMFLT_VV(d0, q1, q0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + break; + case 0xb: VMXOR_MM(VMASK, q2, q2); break; + case 0xc: + AVX_CMP_ORDERED_MASK(); + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); + VMNAND_MM(VMASK, d0, d0); + VMAND_MM(VMASK, VMASK, q2); + break; + case 0xd: VMFLE_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; + case 0xe: VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; + case 0xf: VMXNOR_MM(VMASK, q2, q2); break; + } + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMERGE_VIM(v0, v0, 0x1f); + PUTGY_vector(v0, VECTOR_SEW64); + break; + case 0xE6: + if (!BOX64ENV(dynarec_fastround)) return 0; + INST_NAME("VCVTTPD2DQ Gx, Ex"); + nextop = F8; + GETEY_vector(q0, 0, VECTOR_SEW64); + GETGY_empty_vector(v0); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + q2 = fpu_get_scratch(dyn); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); + VMV_V_V(d0, q0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, vex.l ? 1 : 0.5f); + VFNCVT_RTZ_X_F_W(q2, d0, VECTOR_UNMASKED); + VMV_V_V(v0, q2); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; + case 0x7C: + case 0x7D: + if (!BOX64ENV(dynarec_fastnan)) return 0; + if (opcode == 0x7C) { + INST_NAME("VHADDPD Gx, Vx, Ex"); + } else { + INST_NAME("VHSUBPD Gx, Vx, Ex"); + } + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW64); + q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + q5 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q2, q0, q2, VECTOR_UNMASKED); + else + VFSUB_VV(q2, q0, q2, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q3, q1, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q3, q1, q3, VECTOR_UNMASKED); + else + VFSUB_VV(q3, q1, q3, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q4, VECTOR_UNMASKED); + VAND_VI(q4, q4, -2, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16 << vex.l); + VRGATHEREI16_VV(q5, q3, q4, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(vex.l ? 0x0a : 0x02, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q2, q5); + PUTGY_vector(v0, VECTOR_SEW64); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c index 605aaf2cd..c43bd4768 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c @@ -155,7 +155,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2C: INST_NAME("VCVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -184,7 +184,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2D: INST_NAME("VCVTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -336,15 +336,9 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); FLD(v0, vback, vxoffset + 0); FLD(v1, wback, fixedaddress + 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v1, v0); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v0, v1); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; FSD(v0, gback, gdoffset + 0); if (gd != vex.v) { LD(x3, vback, vxoffset + 8); @@ -410,7 +404,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, SRLI(x4, x4, 29); MOV32w(x5, 0x007fffff); AND(x4, x4, x5); - LUI(x5, 0x7fc00); + MOV32w(x5, 0x7FC00000); OR(x4, x4, x5); OR(x4, x4, x6); FMVWX(v0, x4); @@ -435,15 +429,9 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, v1 = fpu_get_scratch(dyn); FLD(v0, vback, vxoffset + 0); FLD(v1, wback, fixedaddress + 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v0, v1); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v1, v0); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; FSD(v0, gback, gdoffset + 0); if (gd != vex.v) { LD(x3, vback, vxoffset + 8); @@ -598,7 +586,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x7D: INST_NAME("VHSUBPS Gx, Vx, Ex"); nextop = F8; - GETEX(x2, 0, vex.l ? 24 : 8); + GETEX(x2, 0, vex.l ? 28 : 12); GETGX(); GETGY(); GETVX(); @@ -781,7 +769,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x7C: INST_NAME("VHADDPS Gx, Vx, Ex"); nextop = F8; - GETEX(x2, 0, vex.l ? 24 : 8); + GETEX(x2, 0, vex.l ? 28 : 12); GETGX(); GETGY(); GETVX(); @@ -944,7 +932,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLD(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 4 * i); } if (vex.l) { @@ -954,7 +942,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FCVTLD(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); + MOV64x(x3, (int64_t)INT32_MIN); SW(x3, gback, gdoffset + 8 + 4 * i); } } else { diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c index 9cf35d265..d455740ae 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c @@ -60,7 +60,7 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF5: INST_NAME("PDEP Gd, Vd, Ed"); nextop = F8; - GETGD; + GETGDd; GETVD; GETED(0); if (gd == ed || gd == vd) { @@ -94,10 +94,11 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF6: INST_NAME("MULX Gd, Vd, Ed (,RDX)"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; if (rex.w) { + MARKREGs(xRDX); if ((gd == xRDX) || (gd == ed) || (gd == vd)) gb1 = x3; else @@ -118,7 +119,7 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF7: INST_NAME("SHRX Gd, Ed, Vd"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x5, vd, rex.w ? 0x3f : 0x1f); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c index 6582ff1f4..53a54b418 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f2_0f_vector.c @@ -28,7 +28,7 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint8_t nextop, u8; uint8_t gd, ed; int v0, v1, v2; - int q0, q1, q2, d0, d1; + int q0, q1, q2, q3, q4, q5, q6, d0, d1; int64_t fixedaddress; int64_t j64; rex_t rex = vex.rex; @@ -44,10 +44,143 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MAYUSE(j64); switch (opcode) { + case 0x10: + INST_NAME("VMOVSD Gx, [Vx,] Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d0, ed, fixedaddress); + } + GETGY_empty_vector(v0); + if (MODREG) { + if (v0 != q0) + VMV_V_V(v0, q0); + } else { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x11: + INST_NAME("VMOVSD Ex, [Vx,] Gx"); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW64); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q2 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q2, vex.v, 16, VECTOR_SEW64); + VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); + VFMV_S_F(q2, d0); + avx_store_reg_vector(dyn, ninst, x1, q2, ed, 16, VECTOR_SEW64); + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); + FSD(d0, ed, fixedaddress); + SMWRITE2(); + } + break; + case 0x58: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VADDSD Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); + break; + case 0x59: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VMULSD Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); + break; + case 0x5C: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VSUBSD Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); + break; + case 0x5D: + INST_NAME("VMINSD Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); + break; + case 0x5E: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VDIVSD Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); + break; + case 0x5F: + INST_NAME("VMAXSD Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); + break; + case 0x5A: + INST_NAME("VCVTSD2SS Gx, Vx, Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d0, ed, fixedaddress); + } + d1 = fpu_get_scratch(dyn); + FCVTSD(d1, d0); + if (!BOX64ENV(dynarec_fastnan)) { + FEQD(x3, d0, d0); + FMVXD(x4, d0); + BNEZ_MARK(x3); + SRLI(x6, x4, 63); + SLLI(x6, x6, 31); + SRLI(x4, x4, 29); + MOV32w(x5, 0x007fffff); + AND(x4, x4, x5); + MOV32w(x5, 0x7FC00000); + OR(x4, x4, x5); + OR(x4, x4, x6); + FMVWX(d1, x4); + MARK; + } + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VFMV_S_F(v0, d1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; case 0x2A: INST_NAME("VCVTSI2SD Gx, Vx, Ed"); nextop = F8; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -68,18 +201,21 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt FCVTDW(d0, ed, RD_DYN); x87_restoreround(dyn, ninst, u8); GETGY_empty_vector(v0); - if (v0 != q0) + if (v0 != q0) { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW64, 16); VMV_V_V(v0, q0); + } + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); VFMV_S_F(v0, d0); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); break; case 0x2C: INST_NAME("VCVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { - q0 = fpu_get_scratch(dyn); + q0 = VREG((nextop & 7) + (rex.b << 3)); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); VFMV_F_S(d0, q0); } else { @@ -103,25 +239,78 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MOV32w(gd, 0x80000000); } break; + case 0x2D: + INST_NAME("VCVTSD2SI Gd, Ex"); + nextop = F8; + GETGDd; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q0 = VREG((nextop & 7) + (rex.b << 3)); + avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + VFMV_F_S(d0, q0); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLD(d0, ed, fixedaddress); + } + if (!BOX64ENV(dynarec_fastround)) FSFLAGSI(0); + LW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + SRLI(x5, x5, 13); + ANDI(x5, x5, 3); + BEQZ_MARK(x5); + ADDI(x6, xZR, 3); + BEQ_MARK2(x5, x6); + ADDI(x6, xZR, 2); + BEQ_MARK3(x5, x6); + FCVTLDxw(gd, d0, RD_RDN); + B_MARK4_nocond; + MARK; + FCVTLDxw(gd, d0, RD_RNE); + B_MARK4_nocond; + MARK2; + FCVTLDxw(gd, d0, RD_RTZ); + B_MARK4_nocond; + MARK3; + FCVTLDxw(gd, d0, RD_RUP); + MARK4; + if (!rex.w) ZEROUP(gd); + if (!BOX64ENV(dynarec_fastround)) { + FRFLAGS(x5); + ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); + CBZ_NEXT(x5); + if (rex.w) + MOV64x(gd, 0x8000000000000000LL); + else + MOV32w(gd, 0x80000000); + } + break; case 0x70: INST_NAME("VPSHUFLW Gx, Ex, Ib"); nextop = F8; GETEY_vector(q1, 1, VECTOR_SEW16); GETGY_empty_vector(v0); u8 = F8; - SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); q0 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); - d0 = fpu_get_scratch(dyn); - VID_V(q0, VECTOR_UNMASKED); - VMV_V_V(q2, q0); - for (int k = 0; k < 4; ++k) { - VECTOR_LOAD_VMASK(vex.l ? ((1 << k) | (1 << (8 + k))) : (1 << k), x4, vex.l ? 2 : 1); - int delta = (int8_t)((u8 >> (k * 2)) & 3) - k; - if (delta) VADD_VI(d0, q0, delta, VECTOR_UNMASKED); - VMERGE_VVM(q2, q2, delta ? d0 : q0); + MOV64xs(x4, (uint64_t)(u8 & 3) | ((uint64_t)((u8 >> 2) & 3) << 16) | ((uint64_t)((u8 >> 4) & 3) << 32) | ((uint64_t)((u8 >> 6) & 3) << 48), x3); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_X(q0, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q2, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VMERGE_VVM(q0, q0, q2); + if (vex.l) { + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q0); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); + VSLIDEUP_VI_SAFE(q0, q3, 8, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 7, VECTOR_UNMASKED); + VOR_VI(q0, q0, 8, VECTOR_MASKED); } - VRGATHER_VV(v0, q1, q2, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); + VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0x12: @@ -133,31 +322,16 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); VID_V(v2, VECTOR_UNMASKED); VAND_VI(v2, v2, 0x1e, VECTOR_UNMASKED); - VRGATHER_VV(v0, v1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW64); break; case 0x51: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSQRTSD Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); - d0 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); - VFMV_F_S(d0, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLD(d0, ed, fixedaddress); - } - FSQRTD(d0, d0); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW64); + VFSQRT_V(v0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW64); break; case 0xF0: INST_NAME("VLDDQU Gx, Ex"); @@ -167,6 +341,63 @@ uintptr_t dynarec64_AVX_F2_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VMV_V_V(v0, v1); PUTGY_vector(v0, VECTOR_SEW8); break; + case 0xC2: + INST_NAME("VCMPSD Gx, Vx, Ex, Ib"); + nextop = F8; + AVX_SCALAR_CMP(VECTOR_SEW64); + break; + case 0xD0: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VADDSUBPS Gx, Vx, Ex"); + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + VID_V(q2, VECTOR_UNMASKED); + VAND_VI(q2, q2, 1, VECTOR_UNMASKED); + VMSEQ_VX(VMASK, q2, xZR, VECTOR_UNMASKED); + VFSUB_VV(v0, q0, q1, VECTOR_MASKED); + VXOR_VI(VMASK, VMASK, 0x1f, VECTOR_UNMASKED); + VFADD_VV(v0, q0, q1, VECTOR_MASKED); + PUTGY_vector(v0, VECTOR_SEW32); + break; + case 0x7C: + case 0x7D: + if (!BOX64ENV(dynarec_fastnan)) return 0; + if (opcode == 0x7C) { + INST_NAME("VHADDPS Gx, Vx, Ex"); + } else { + INST_NAME("VHSUBPS Gx, Vx, Ex"); + } + nextop = F8; + GETGY_empty_VYEY_vector(v0, q0, q1, VECTOR_SEW32); + q2 = fpu_get_scratch(dyn); + q3 = fpu_get_scratch(dyn); + q4 = fpu_get_scratch(dyn); + q5 = fpu_get_scratch(dyn); + q6 = fpu_get_scratch(dyn); + VSLIDEDOWN_VI(q2, q0, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q2, q0, q2, VECTOR_UNMASKED); + else + VFSUB_VV(q2, q0, q2, VECTOR_UNMASKED); + VSLIDEDOWN_VI(q3, q1, 1, VECTOR_UNMASKED); + if (opcode == 0x7C) + VFADD_VV(q3, q1, q3, VECTOR_UNMASKED); + else + VFSUB_VV(q3, q1, q3, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q4, VECTOR_UNMASKED); + VAND_VI(q5, q4, 1, VECTOR_UNMASKED); + VSLL_VI(q5, q5, 1, VECTOR_UNMASKED); + VAND_VI(q4, q4, 4, VECTOR_UNMASKED); + VOR_VV(q4, q4, q5, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16 << vex.l); + VRGATHEREI16_VV(q5, q2, q4, VECTOR_UNMASKED); + VRGATHEREI16_VV(q6, q3, q4, VECTOR_UNMASKED); + VECTOR_LOAD_VMASK(vex.l ? 0xcc : 0x0c, x4, vex.l ? 2 : 1); + VMERGE_VVM(v0, q5, q6); + PUTGY_vector(v0, VECTOR_SEW32); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c index e8f453606..ed249ceb5 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c @@ -223,7 +223,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, case 0x2C: INST_NAME("VCVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -249,6 +249,37 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, } } break; + case 0x2D: + INST_NAME("VCVTSS2SI Gd, Ex"); + nextop = F8; + GETGDd; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + sse_forget_reg(dyn, ninst, x1, ed); + FLW(d0, xEmu, offsetof(x64emu_t, xmm[ed])); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0); + FLW(d0, wback, fixedaddress); + } + if (!BOX64ENV(dynarec_fastround)) { + FSFLAGSI(0); + } + u8 = sse_setround(dyn, ninst, x5, x6); + FCVTSxw(gd, d0, RD_DYN); + x87_restoreround(dyn, ninst, u8); + if (!rex.w) ZEROUP(gd); + if (!BOX64ENV(dynarec_fastround)) { + FRFLAGS(x5); + ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); + CBZ_NEXT(x5); + if (rex.w) { + MOV64x(gd, 0x8000000000000000LL); + } else { + MOV32w(gd, 0x80000000); + } + } + break; case 0x58: INST_NAME("VADDSS Gx, Vx, Ex"); nextop = F8; @@ -346,7 +377,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FRFLAGS(x5); ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQZ(x5, 4 + 4); - LUI(x3, 0x80000000 >> 12); + MOV64x(x3, (int64_t)INT32_MIN); } SW(x3, gback, gdoffset + i * 4); } @@ -362,7 +393,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, FRFLAGS(x5); ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQZ(x5, 4 + 4); - LUI(x3, 0x80000000 >> 12); + MOV64x(x3, (int64_t)INT32_MIN); } SW(x3, gback, gyoffset + i * 4); } @@ -420,15 +451,9 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d1 = fpu_get_scratch(dyn); FLW(d0, vback, vxoffset); FLW(d1, wback, fixedaddress); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d0, d1); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; FSW(d0, gback, gdoffset); if (gd != vex.v) { LWU(x2, vback, vxoffset + 4); @@ -449,15 +474,9 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, d1 = fpu_get_scratch(dyn); FLW(d0, vback, vxoffset); FLW(d1, wback, fixedaddress); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d1, d0); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; FSW(d0, gback, gdoffset); if (gd != vex.v) { LWU(x2, vback, vxoffset + 4); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c index 9c9b2b17c..a3a2366fd 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c @@ -60,7 +60,7 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF5: INST_NAME("PEXT Gd, Vd, Ed"); nextop = F8; - GETGD; + GETGDd; GETVD; GETED(0); if (gd == ed || gd == vd) { @@ -95,7 +95,7 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0xF7: INST_NAME("SARX Gd, Ed, Vd"); nextop = F8; - GETGD; + GETGDd; GETED(0); GETVD; ANDI(x5, vd, rex.w ? 0x3f : 0x1f); diff --git a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c index f4866e29b..eb419a61a 100644 --- a/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_avx_f3_0f_vector.c @@ -28,7 +28,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt uint8_t nextop, u8; uint8_t gd, ed; int v0, v1, v2; - int q0, q1, q2, d0, d1; + int q0, q1, q2, q3, d0, d1; int64_t fixedaddress; int64_t j64; rex_t rex = vex.rex; @@ -44,6 +44,109 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MAYUSE(j64); switch (opcode) { + case 0x10: + INST_NAME("VMOVSS Gx, [Vx,] Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLW(d0, ed, fixedaddress); + } + GETGY_empty_vector(v0); + if (MODREG) { + if (v0 != q0) + VMV_V_V(v0, q0); + } else { + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + } + VFMV_S_F(v0, d0); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + break; + case 0x11: + INST_NAME("VMOVSS Ex, [Vx,] Gx"); + nextop = F8; + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + q0 = VREG(gd); + avx_load_reg_vector(dyn, ninst, x1, q0, gd, 16, VECTOR_SEW32); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + q2 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q2, vex.v, 16, VECTOR_SEW32); + VFMV_F_S(d0 = fpu_get_scratch(dyn), q0); + VFMV_S_F(q2, d0); + avx_store_reg_vector(dyn, ninst, x1, q2, ed, 16, VECTOR_SEW32); + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VSE32_V(q0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + SMWRITE2(); + } + break; + case 0x5A: + INST_NAME("VCVTSS2SD Gx, Vx, Ex"); + nextop = F8; + d0 = fpu_get_scratch(dyn); + if (MODREG) { + q1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d0, q1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + FLW(d0, ed, fixedaddress); + } + d1 = fpu_get_scratch(dyn); + FCVTDS(d1, d0); + if (!BOX64ENV(dynarec_fastnan)) { + FEQS(x3, d0, d0); + FMVXW(x4, d0); + BNEZ_MARK(x3); + SRLIW(x5, x4, 31); + SLLI(x5, x5, 63); + SLLI(x4, x4, 41); + SRLI(x4, x4, 12); + OR(x4, x4, x5); + MOV64x(x5, 0x7ff8000000000000ULL); + OR(x4, x4, x5); + FMVDX(d1, x4); + MARK; + } + q0 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW64); + GETGY_empty_vector(v0); + if (v0 != q0) + VMV_V_V(v0, q0); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VFMV_S_F(v0, d1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; + case 0x7E: + INST_NAME("VMOVQ Gx, Ex"); + nextop = F8; + if (MODREG) { + v1 = fpu_get_scratch(dyn); + avx_load_reg_vector(dyn, ninst, x1, v1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW64); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VMV_X_S(x5, v1); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); + LD(x5, ed, fixedaddress); + } + GETGY_empty_vector(v0); + SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW64); + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMV_S_X(v0, x5); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW64); + break; case 0x12: INST_NAME("VMOVSLDUP Gx, Ex"); nextop = F8; @@ -53,7 +156,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW32); VID_V(v2, VECTOR_UNMASKED); VAND_VI(v2, v2, 0x1e, VECTOR_UNMASKED); - VRGATHER_VV(v0, v1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x16: @@ -66,16 +169,26 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VID_V(v2, VECTOR_UNMASKED); VOR_VI(v2, v2, 1, VECTOR_UNMASKED); VAND_VI(v2, v2, 0x1f, VECTOR_UNMASKED); - VRGATHER_VV(v0, v1, v2, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, v2, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW32); break; case 0x6F: INST_NAME("VMOVDQU Gx, Ex"); nextop = F8; - GETEY_vector(v1, 0, VECTOR_SEW8); - GETGY_empty_vector(v0); - VMV_V_V(v0, v1); - PUTGY_vector(v0, VECTOR_SEW8); + if (!MODREG) { + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); + v0 = sse_get_reg_empty_vector(dyn, ninst, x1, gd); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); + VLE8_V(v0, ed, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16 << vex.l, VECTOR_SEW8); + } else { + GETEY_vector(v1, 0, VECTOR_SEW8); + GETGY_empty_vector(v0); + VMV_V_V(v0, v1); + PUTGY_vector(v0, VECTOR_SEW8); + } break; case 0x7F: INST_NAME("VMOVDQU Ex, Gx"); @@ -94,7 +207,7 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt case 0x2A: INST_NAME("VCVTSI2SS Gx, Vx, Ed"); nextop = F8; - q0 = fpu_get_scratch(dyn); + q0 = VREG(vex.v); avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); if (MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -107,26 +220,54 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt LW(x4, ed, fixedaddress); ed = x4; } - u8 = sse_setround(dyn, ninst, x5, x6); + LW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + SRLI(x5, x5, 13); + ANDI(x5, x5, 3); d0 = fpu_get_scratch(dyn); + BEQZ_MARK(x5); + ADDI(x6, xZR, 3); + BEQ_MARK2(x5, x6); + ADDI(x6, xZR, 2); + BEQ_MARK3(x5, x6); + if (rex.w) + FCVTSL(d0, ed, RD_RDN); + else + FCVTSW(d0, ed, RD_RDN); + B_MARK4_nocond; + MARK; + if (rex.w) + FCVTSL(d0, ed, RD_RNE); + else + FCVTSW(d0, ed, RD_RNE); + B_MARK4_nocond; + MARK2; + if (rex.w) + FCVTSL(d0, ed, RD_RTZ); + else + FCVTSW(d0, ed, RD_RTZ); + B_MARK4_nocond; + MARK3; if (rex.w) - FCVTSL(d0, ed, RD_DYN); + FCVTSL(d0, ed, RD_RUP); else - FCVTSW(d0, ed, RD_DYN); - x87_restoreround(dyn, ninst, u8); + FCVTSW(d0, ed, RD_RUP); + MARK4; GETGY_empty_vector(v0); - if (v0 != q0) + if (v0 != q0) { + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW32, 16); VMV_V_V(v0, q0); + } + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); VFMV_S_F(v0, d0); avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); break; case 0x2C: INST_NAME("VCVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { - q0 = fpu_get_scratch(dyn); + q0 = VREG((nextop & 7) + (rex.b << 3)); avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); VFMV_F_S(d0, q0); } else { @@ -147,78 +288,74 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt MOV32w(gd, 0x80000000); } break; - case 0x51: - if (!BOX64ENV(dynarec_fastnan)) return 0; - INST_NAME("VSQRTSS Gx, Vx, Ex"); + case 0x2D: + INST_NAME("VCVTSS2SI Gd, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); + GETGDd; d0 = fpu_get_scratch(dyn); if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d0, q1); + q0 = VREG((nextop & 7) + (rex.b << 3)); + avx_load_reg_vector(dyn, ninst, x1, q0, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); + VFMV_F_S(d0, q0); } else { SMREAD(); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); FLW(d0, ed, fixedaddress); } - FSQRTS(d0, d0); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + if (!BOX64ENV(dynarec_fastround)) FSFLAGSI(0); + LW(x5, xEmu, offsetof(x64emu_t, mxcsr)); + SRLI(x5, x5, 13); + ANDI(x5, x5, 3); + BEQZ_MARK(x5); + ADDI(x6, xZR, 3); + BEQ_MARK2(x5, x6); + ADDI(x6, xZR, 2); + BEQ_MARK3(x5, x6); + FCVTSxw(gd, d0, RD_RDN); + B_MARK4_nocond; + MARK; + FCVTSxw(gd, d0, RD_RNE); + B_MARK4_nocond; + MARK2; + FCVTSxw(gd, d0, RD_RTZ); + B_MARK4_nocond; + MARK3; + FCVTSxw(gd, d0, RD_RUP); + MARK4; + if (!rex.w) ZEROUP(gd); + if (!BOX64ENV(dynarec_fastround)) { + FRFLAGS(x5); + ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); + CBZ_NEXT(x5); + if (rex.w) + MOV64x(gd, 0x8000000000000000LL); + else + MOV32w(gd, 0x80000000); + } + break; + case 0x51: + if (!BOX64ENV(dynarec_fastnan)) return 0; + INST_NAME("VSQRTSS Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFSQRT_V(v0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x58: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VADDSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FADDS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFADD_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x59: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VMULSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FMULS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFMUL_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x5B: INST_NAME("VCVTTPS2DQ Gx, Ex"); @@ -247,51 +384,33 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VSUBSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FSUBS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFSUB_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); + break; + case 0x5D: + INST_NAME("VMINSS Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x5E: if (!BOX64ENV(dynarec_fastnan)) return 0; INST_NAME("VDIVSS Gx, Vx, Ex"); nextop = F8; - q0 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, VECTOR_SEW32); - d1 = fpu_get_scratch(dyn); - if (MODREG) { - q1 = fpu_get_scratch(dyn); - avx_load_reg_vector(dyn, ninst, x1, q1, (nextop & 7) + (rex.b << 3), 16, VECTOR_SEW32); - VFMV_F_S(d1, q1); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - FLW(d1, ed, fixedaddress); - } - d0 = fpu_get_scratch(dyn); - VFMV_F_S(d0, q0); - FDIVS(d0, d0, d1); - GETGY_empty_vector(v0); - if (v0 != q0) - VMV_V_V(v0, q0); - VFMV_S_F(v0, d0); - avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, VECTOR_SEW32); + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VFDIV_VV(v0, q0, q1, VECTOR_UNMASKED); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); + break; + case 0x5F: + INST_NAME("VMAXSS Gx, Vx, Ex"); + nextop = F8; + AVX_SCALAR_OP_PROLOG(VECTOR_SEW32); + VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); + VMERGE_VVM(v0, q1, q0); + AVX_SCALAR_OP_STORE(VECTOR_SEW32); break; case 0x70: INST_NAME("VPSHUFHW Gx, Ex, Ib"); @@ -299,19 +418,27 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt GETEY_vector(q1, 1, VECTOR_SEW16); GETGY_empty_vector(v0); u8 = F8; - SET_AVX_VECTOR_WIDTH(x1, VECTOR_SEW16); q0 = fpu_get_scratch(dyn); q2 = fpu_get_scratch(dyn); - d0 = fpu_get_scratch(dyn); - VID_V(q0, VECTOR_UNMASKED); - VMV_V_V(q2, q0); - for (int k = 0; k < 4; ++k) { - VECTOR_LOAD_VMASK(vex.l ? ((1 << (4 + k)) | (1 << (12 + k))) : (1 << (4 + k)), x4, vex.l ? 2 : 1); - int delta = (int8_t)((u8 >> (k * 2)) & 3) - k; - if (delta) VADD_VI(d0, q0, delta, VECTOR_UNMASKED); - VMERGE_VVM(q2, q2, delta ? d0 : q0); + MOV64xs(x4, (uint64_t)(4 + (u8 & 3)) | ((uint64_t)(4 + ((u8 >> 2) & 3)) << 16) | ((uint64_t)(4 + ((u8 >> 4) & 3)) << 32) | ((uint64_t)(4 + ((u8 >> 6) & 3)) << 48), x3); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); + VMV_V_X(q0, x4); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); + VID_V(q2, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 3, VECTOR_UNMASKED); + VMERGE_VVM(q0, q2, q0); + if (vex.l) { + q3 = fpu_get_scratch(dyn); + VMV_V_V(q3, q0); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 2); + VSLIDEUP_VI_SAFE(q0, q3, 8, VECTOR_UNMASKED); + VID_V(VMASK, VECTOR_UNMASKED); + VMSGT_VI(VMASK, VMASK, 7, VECTOR_UNMASKED); + VOR_VI(q0, q0, 8, VECTOR_MASKED); } - VRGATHER_VV(v0, q1, q2, VECTOR_UNMASKED); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW16, 16 << vex.l); + VRGATHER_VV_SAFE(v0, q1, q0, VECTOR_UNMASKED); PUTGY_vector(v0, VECTOR_SEW16); break; case 0xE6: @@ -334,6 +461,11 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt VMV_V_V(v0, d0); PUTGY_vector(v0, VECTOR_SEW64); break; + case 0xC2: + INST_NAME("VCMPSS Gx, Vx, Ex, Ib"); + nextop = F8; + AVX_SCALAR_CMP(VECTOR_SEW32); + break; default: DEFAULT_VECTOR; } diff --git a/src/dynarec/rv64/dynarec_rv64_consts.c b/src/dynarec/rv64/dynarec_rv64_consts.c index 26f7cb184..75ebd0123 100644 --- a/src/dynarec/rv64/dynarec_rv64_consts.c +++ b/src/dynarec/rv64/dynarec_rv64_consts.c @@ -31,6 +31,9 @@ void PrintTrace() {} #endif void* create_updateflags(); +extern void rv64_next_invalid(); +extern void rv64_crc_autocrc(); +extern void rv64_crc_autocrc_zbc(); uintptr_t getConst(rv64_consts_t which) { @@ -140,6 +143,9 @@ uintptr_t getConst(rv64_consts_t which) case const_context: return (uintptr_t)my_context; case const_lead0tab: return (uintptr_t)lead0tab; case const_deBruijn64tab: return (uintptr_t)deBruijn64tab; + case const_native_next_invalid: return (uintptr_t)rv64_next_invalid; + case const_rv64_crc_autocrc: return (uintptr_t)rv64_crc_autocrc; + case const_rv64_crc_autocrc_zbc: return (uintptr_t)rv64_crc_autocrc_zbc; case const_last: dynarec_log(LOG_NONE, "Warning, const last used\n"); return (uintptr_t)native_ud; diff --git a/src/dynarec/rv64/dynarec_rv64_consts.h b/src/dynarec/rv64/dynarec_rv64_consts.h index 0cb183de5..7c80d431f 100644 --- a/src/dynarec/rv64/dynarec_rv64_consts.h +++ b/src/dynarec/rv64/dynarec_rv64_consts.h @@ -108,6 +108,9 @@ typedef enum rv64_consts_s { const_context, const_lead0tab, const_deBruijn64tab, + const_native_next_invalid, + const_rv64_crc_autocrc, + const_rv64_crc_autocrc_zbc, const_last } rv64_consts_t; diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c index 239219177..7b92d866f 100644 --- a/src/dynarec/rv64/dynarec_rv64_d9.c +++ b/src/dynarec/rv64/dynarec_rv64_d9.c @@ -142,18 +142,13 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ANDI(x5, x5, 7); // (emu->top + i)&7 } // load x2 with ST0 anyway, for sign extraction - if (cpuext.zba) - SH3ADD(x1, x5, xEmu); - else { - SLLI(x5, x5, 3); - ADD(x1, xEmu, x5); - } + ADDSL(x1, xEmu, x5, 3, x5); LD(x2, x1, offsetof(x64emu_t, x87)); // load tag if (i2 >= 0) { LHU(x3, xEmu, offsetof(x64emu_t, fpu_tags)); if (i2 > 0) { - LUI(x5, 0xffff0); + MOV64x(x5, 0xFFFFFFFFFFFF0000); OR(x3, x3, x5); SRLI(x3, x3, i2 * 2); } @@ -325,7 +320,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xF6: INST_NAME("FDECSTP"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); LW(x2, xEmu, offsetof(x64emu_t, top)); SUBI(x2, x2, 1); ANDI(x2, x2, 7); @@ -333,7 +328,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xF7: INST_NAME("FINCSTP"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); LW(x2, xEmu, offsetof(x64emu_t, top)); ADDI(x2, x2, 1); ANDI(x2, x2, 7); @@ -521,12 +516,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (!BOX64ENV(dynarec_fastnan)) { FEQS(x5, s0, s0); BNEZ_MARK(x5); - FMVXD(x5, v1); - SRLI(x5, x5, 63); - BNEZ_MARK2(x5); - B_MARK_nocond; - MARK2; - FNEGS(s0, s0); + X87_DOUBLE_TO_FLOAT(s0, v1, x5, x6); MARK; } } @@ -548,12 +538,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni if (!BOX64ENV(dynarec_fastnan)) { FEQS(x5, v1, v1); BNEZ_MARK(x5); - FMVXD(x5, s1); - SRLI(x5, x5, 63); - BNEZ_MARK2(x5); - B_MARK_nocond; - MARK2; - FNEGS(v1, v1); + X87_DOUBLE_TO_FLOAT(v1, s1, x5, x6); MARK; } } @@ -563,7 +548,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 4: INST_NAME("FLDENV Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE? + BARRIER(BARRIER_FLOAT); // maybe only x87, not SSE? addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, 0); CALL(const_fpu_loadenv, -1, ed, x2); @@ -581,7 +566,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 6: INST_NAME("FNSTENV Ed"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE? + BARRIER(BARRIER_FLOAT); // maybe only x87, not SSE? addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); MOV32w(x2, 0); CALL(const_fpu_savenv, -1, ed, x2); diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c index c9916aebc..4991277c2 100644 --- a/src/dynarec/rv64/dynarec_rv64_dd.c +++ b/src/dynarec/rv64/dynarec_rv64_dd.c @@ -152,14 +152,14 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 4: INST_NAME("FRSTOR m108byte"); MESSAGE(LOG_DUMP, "Need Optimization (FRSTOR)\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x4, x6, &fixedaddress, rex, NULL, 0, 0); CALL(const_native_frstor, -1, ed, 0); break; case 6: INST_NAME("FNSAVE m108byte"); MESSAGE(LOG_DUMP, "Need Optimization\n"); - fpu_purgecache(dyn, ninst, 0, x1, x2, x3); + BARRIER(BARRIER_FLOAT); addr = geted(dyn, addr, ninst, nextop, &ed, x4, x6, &fixedaddress, rex, NULL, 0, 0); CALL(const_native_fsave, -1, ed, 0); NATIVE_RESTORE_X87PC(); diff --git a/src/dynarec/rv64/dynarec_rv64_de.c b/src/dynarec/rv64/dynarec_rv64_de.c index d9cc1492e..fb971f587 100644 --- a/src/dynarec/rv64/dynarec_rv64_de.c +++ b/src/dynarec/rv64/dynarec_rv64_de.c @@ -30,10 +30,13 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni uint8_t nextop = F8; uint8_t wback; uint8_t u8; + uint8_t ed; int64_t fixedaddress; int v1, v2, s1, s2; int64_t j64; + MAYUSE(ed); + MAYUSE(v2); MAYUSE(v1); @@ -260,8 +263,151 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } else switch ((nextop >> 3) & 7) { - default: - DEFAULT; + case 0: + INST_NAME("FIADD ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FADDD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 1: + INST_NAME("FIMUL ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FMULD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 2: + INST_NAME("FICOM ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + FCOMD(v1, v2, x1, x2, x3, x4, x5); + break; + case 3: + INST_NAME("FICOMP ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + FCOMD(v1, v2, x1, x2, x3, x4, x5); + X87_POP_OR_FAIL(dyn, ninst, x3); + break; + case 4: + INST_NAME("FISUB ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FSUBD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 5: + INST_NAME("FISUBR ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v2); + FMVD(s2, v1); + } + FSUBD(v1, v2, v1); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 6: + INST_NAME("FIDIV ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v1); + FMVD(s2, v2); + } + FDIVD(v1, v1, v2); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; + case 7: + INST_NAME("FIDIVR ST0, Ed"); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); + v2 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); + LH(x1, ed, fixedaddress); + FCVTDW(v2, x1, RD_RNE); // i32 -> double + if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5); + if (!BOX64ENV(dynarec_fastnan)) { + s1 = fpu_get_scratch(dyn); + s2 = fpu_get_scratch(dyn); + FMVD(s1, v2); + FMVD(s2, v1); + } + FDIVD(v1, v2, v1); + if (!BOX64ENV(dynarec_fastnan)) { + X87_ARITH_NAN_FIX_D(v1, s1, s2, x5, x6, x4); + } + X87_CHECK_PRECISION(v1); + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); + break; } return addr; } diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c index b0e6b20d2..f1e2a4a53 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c @@ -95,9 +95,9 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s if (!rex.w && s1 != s2) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { @@ -137,9 +137,9 @@ void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } if (!rex.w) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -233,9 +233,9 @@ void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } if (!rex.w) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -273,9 +273,9 @@ void emit_or32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in } if (!rex.w) { IFX (X_ZF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -388,9 +388,9 @@ void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s AND(s1, s1, s2); // res = s1 & s2 if (!rex.w) { IFX (X_ZF | X_SF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -426,9 +426,9 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } if (!rex.w) { IFX (X_ZF | X_SF) - ZEROUP(s1); - else if (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion) - ZEROUP(s1); + ZEROUP_RESULT(s1); + else if (NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index a36886abb..751451d00 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -72,8 +72,9 @@ void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s4); @@ -95,8 +96,9 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i MOV64x(s2, c); ADD(s1, s1, s2); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } return; } @@ -160,8 +162,9 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s4); @@ -447,8 +450,9 @@ void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w ? 64 : 32); IFX (X_ZF) { @@ -472,8 +476,9 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i MOV64xw(s2, c); SUBxw(s1, s1, s2); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } return; } @@ -514,8 +519,9 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w ? 64 : 32); IFX (X_ZF) { @@ -671,8 +677,9 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s4, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s2); @@ -724,8 +731,9 @@ void emit_dec32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s4, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s2); @@ -1018,8 +1026,9 @@ void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PEND) { @@ -1079,8 +1088,9 @@ void emit_neg32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s4, s5); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s2); @@ -1328,8 +1338,9 @@ void emit_adc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s5, s6); } - if (!rex.w && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w && NEED_ZEROUP32(s1) && (IS_GPR(s1) || dyn->insts[ninst].nat_flags_fusion)) { + ZEROUP_RESULT(s1); } IFX (X_PF) { emit_pf(dyn, ninst, s1, s3, s4); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 390e61a45..2e758209a 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -671,8 +671,9 @@ void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -689,7 +690,7 @@ void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5) { if (!c) { - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); return; } @@ -725,8 +726,9 @@ void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -777,8 +779,9 @@ void emit_shr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -835,8 +838,12 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } - if (!rex.w && c == 0) { - ZEROUP(s1); + UP32_WRITE32(s1); + if (!rex.w) { + if (c == 0) + ZEROUP_RESULT(s1); + else + UP32_ZERO(s1); // SRLIW with c>0 always clears bit 31 } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -854,7 +861,7 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { if (!c) { - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); return; } @@ -893,8 +900,9 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -935,8 +943,9 @@ void emit_sar32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX (X_SF) { SET_FLAGS_LTZ(s1, F_SF, s3, s4); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_ZF) { SET_FLAGS_EQZ(s1, F_ZF, s3); @@ -952,8 +961,9 @@ void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_CF | X_OF) { @@ -974,7 +984,7 @@ void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s ROL(s1, s1, s2); } else { ROLW(s1, s1, s2); - ZEROUP(s1); + ZEROUP_RESULT(s1); } } else { SLLxw(s3, s1, s2); @@ -999,8 +1009,9 @@ void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_CF) ANDI(xFlags, xFlags, ~(1UL << F_CF)); @@ -1019,7 +1030,7 @@ void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s ROR(s1, s1, s2); } else { RORW(s1, s1, s2); - ZEROUP(s1); + ZEROUP_RESULT(s1); } } else { SRLxw(s3, s1, s2); @@ -1480,7 +1491,7 @@ void emit_rcl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, if (!c) return; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1509,7 +1520,7 @@ void emit_rcl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SRLIxw(s5, s1, (rex.w ? 65 : 33) - c); OR(s1, s4, s5); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1520,7 +1531,7 @@ void emit_rcr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, if (!c) return; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1549,7 +1560,7 @@ void emit_rcr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SLLIxw(s5, s1, (rex.w ? 65 : 33) - c); OR(s1, s4, s5); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1558,7 +1569,7 @@ void emit_rcl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1597,7 +1608,7 @@ void emit_rcl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SRL(s5, s1, s5); OR(s4, s4, s5); MV(s1, s4); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1606,7 +1617,7 @@ void emit_rcr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s { int64_t j64; SET_DFNONE(); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w) ZEROUP_RESULT(s1); IFX (X_OF) { ANDI(xFlags, xFlags, ~(1UL << F_OF2)); @@ -1644,7 +1655,7 @@ void emit_rcr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SLL(s5, s1, s5); OR(s4, s4, s5); MV(s1, s4); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR, s3, xZR); } @@ -1687,7 +1698,7 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, { c &= rex.w ? 0x3f : 0x1f; if (!c) { - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); return; } @@ -1714,7 +1725,7 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, OR(s1, s3, s1); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_CF) { ANDI(s4, s1, 1 << F_CF); @@ -1786,7 +1797,7 @@ void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, OR(s1, s3, s1); } - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_CF) { SRLIxw(s3, s1, rex.w ? 63 : 31); @@ -1828,8 +1839,9 @@ void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin SLLIxw(s1, s2, (rex.w ? 64 : 32) - c); OR(s1, s1, s3); + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_SF) { SRLIxw(s3, s1, rex.w ? 63 : 31); @@ -1855,7 +1867,9 @@ void emit_shrd16c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin IFX (X_PEND) { if (c) { MOV64x(s3, c); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s4, s2, 16); + OR(s3, s3, s4); + SW(s3, xEmu, offsetof(x64emu_t, op2)); } else SH(xZR, xEmu, offsetof(x64emu_t, op2)); SH(s1, xEmu, offsetof(x64emu_t, op1)); @@ -1946,7 +1960,7 @@ void emit_shld32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin SRLIxw(s1, s2, (rex.w ? 64 : 32) - c); OR(s1, s1, s3); - if (!rex.w) ZEROUP(s1); + UP32_WRITE32(s1); if (!rex.w && NEED_ZEROUP32(s1)) ZEROUP_RESULT(s1); IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); @@ -2002,8 +2016,9 @@ void emit_shrd32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_ZF) { SET_FLAGS_EQZ(s1, F_ZF, s5); @@ -2056,8 +2071,9 @@ void emit_shld32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int IFX (X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); } + UP32_WRITE32(s1); if (!rex.w) { - ZEROUP(s1); + ZEROUP_RESULT(s1); } IFX (X_ZF) { SET_FLAGS_EQZ(s1, F_ZF, s5); @@ -2079,7 +2095,9 @@ void emit_shld16c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin IFX (X_PEND) { if (c) { MOV64x(s3, c); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s4, s2, 16); + OR(s3, s3, s4); + SW(s3, xEmu, offsetof(x64emu_t, op2)); } else SH(xZR, xEmu, offsetof(x64emu_t, op2)); SH(s1, xEmu, offsetof(x64emu_t, op1)); @@ -2147,7 +2165,9 @@ void emit_shld16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, CLEAR_FLAGS(); IFX (X_PEND) { SH(s1, xEmu, offsetof(x64emu_t, op1)); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s5, s2, 16); + OR(s5, s5, s3); + SW(s5, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shld16); } else IFXORNAT (X_ALL) { SET_DFNONE(); @@ -2209,7 +2229,9 @@ void emit_shrd16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, CLEAR_FLAGS(); IFX (X_PEND) { SH(s1, xEmu, offsetof(x64emu_t, op1)); - SH(s3, xEmu, offsetof(x64emu_t, op2)); + SLLI(s5, s2, 16); + OR(s5, s5, s3); + SW(s5, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_shrd16); } else IFXORNAT (X_ALL) { SET_DFNONE(); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index d5280a016..edfe69491 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -232,17 +232,25 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s NAT_FLAGS_ENABLE_CARRY(); NAT_FLAGS_ENABLE_SIGN(); if (dyn->insts[ninst].nat_flags_fusion) { - if (rex.w) { + if (rex.w) NAT_FLAGS_OPS(s1, s2, s3, s4); - } else { + else { + int op1 = s3; + int op2 = s4; if (dyn->insts[ninst].nat_flags_needsign) { SEXT_W(s3, s1); SEXT_W(s4, s2); } else { - ZEXTW2(s3, s1); - ZEXTW2(s4, s2); + if (isUpper32Zero(dyn, ninst, s1)) + op1 = s1; + else + ZEXTW2(s3, s1); + if (isUpper32Zero(dyn, ninst, s2)) + op2 = s2; + else + ZEXTW2(s4, s2); } - NAT_FLAGS_OPS(s3, s4, s5, xZR); + NAT_FLAGS_OPS(op1, op2, s5, s6); } } } @@ -270,7 +278,7 @@ void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, uint8_t nextop, int } int res = s1; IFX (X_ZF | X_PF) { - if (!rex.w && MODREG) { + if (!rex.w && MODREG && !isUpper32Zero(dyn, ninst, s1)) { ZEXTW2(s5, s1); res = s5; } @@ -419,7 +427,7 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int } IFX (X_SF | X_ZF) { - if (!rex.w) ZEROUP(s3); + if (!rex.w && !isUpper32Zero(dyn, ninst, s1) && !isUpper32Zero(dyn, ninst, s2)) ZEROUP(s3); } IFX (X_SF) { diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index 1d27850c0..ac2ba5375 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -176,24 +176,22 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); if (rex.w) - SRAI(x1, gd, 6); + SRAI(x1, gd, 3); else - SRAIW(x1, gd, 5); - if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } - ADDSLy(x3, wback, x1, 2 + rex.w, x1); - ed = x1; - wback = x3; - MARKLOCK; - LRxw(ed, wback, 1, 1); - BEXT(x4, ed, gd, x2); + SRAIW(x1, gd, 3); + ADD(x2, wback, x1); + ANDI(x4, gd, 7); + ANDI(x5, x2, 0b11); + SLLI(x5, x5, 3); + OR(x4, x4, x5); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); + AMOOR_W(x6, x5, x2, 1, 1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); ANDI(xFlags, xFlags, ~1); - OR(xFlags, xFlags, x4); - ADDI(x4, xZR, 1); - ANDI(x2, gd, rex.w ? 0x3f : 0x1f); - SLL(x4, x4, x2); - OR(ed, ed, x4); - SCxw(x7, ed, wback, 1, 1); - BNEZ_MARKLOCK(x7); + OR(xFlags, xFlags, x6); } break; case 0xB0: @@ -267,6 +265,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("LOCK CMPXCHG Ed, Gd"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); GETGD; + MARKREGs(xRAX); addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); UFLAG_IF { MVxw(x6, xRAX); } ANDI(x1, wback, (1 << (rex.w + 2)) - 1); @@ -318,24 +317,55 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETGD; addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); if (rex.w) - SRAI(x1, gd, 6); + SRAI(x1, gd, 3); else - SRAIW(x1, gd, 5); - if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } - ADDSLy(x3, wback, x1, 2 + rex.w, x1); - ed = x1; - wback = x3; - MARKLOCK; - LRxw(ed, wback, 1, 1); - BEXT(x4, ed, gd, x2); // F_CF is 1 + SRAIW(x1, gd, 3); + ADD(x2, wback, x1); + ANDI(x4, gd, 7); + ANDI(x5, x2, 0b11); + SLLI(x5, x5, 3); + OR(x4, x4, x5); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); + XORI(x5, x5, -1); + AMOAND_W(x6, x5, x2, 1, 1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); + ANDI(xFlags, xFlags, ~1); + OR(xFlags, xFlags, x6); + } + break; + case 0xBB: + nextop = F8; + if (MODREG) { + INST_NAME("Invalid LOCK"); + UDF(); + *need_epilog = 1; + *ok = 0; + } else { + INST_NAME("LOCK BTC Ed, Gd"); + SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); + SET_DFNONE(); + GETGD; + addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + if (rex.w) + SRAI(x1, gd, 3); + else + SRAIW(x1, gd, 3); + ADD(x2, wback, x1); + ANDI(x4, gd, 7); + ANDI(x5, x2, 0b11); + SLLI(x5, x5, 3); + OR(x4, x4, x5); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); + AMOXOR_W(x6, x5, x2, 1, 1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); ANDI(xFlags, xFlags, ~1); - OR(xFlags, xFlags, x4); - ADDI(x4, xZR, 1); - ANDI(x2, gd, rex.w ? 0x3f : 0x1f); - SLL(x4, x4, x2); - ANDN(ed, ed, x4, x4); - SCxw(x7, ed, wback, 1, 1); - BNEZ_MARKLOCK(x7); + OR(xFlags, xFlags, x6); } break; case 0xBA: @@ -366,27 +396,31 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); u8 = F8; if (rex.w) u8 &= 63; else u8 &= 31; - ANDI(x3, wback, rex.w ? ~7 : ~3); // aligned word if (((nextop >> 3) & 7) == 4) { LDxw(x4, wback, 0); // read only, no atomic needed - } else { - MOV64xw(x6, 1LL << u8); // bit mask - MARKLOCK; - LRxw(x4, x3, 1, 1); BEXTI(x7, x4, u8); // old bit ANDI(xFlags, xFlags, ~1); OR(xFlags, xFlags, x7); // CF = old bit - SLLI(x7, x7, u8); // old bit at position + } else { + ADDI(x2, wback, u8 >> 3); + ANDI(x4, x2, 0b11); + SLLI(x4, x4, 3); + ORI(x4, x4, u8 & 7); + ANDI(x2, x2, ~0b11); + ADDI(x5, xZR, 1); + SLL(x5, x5, x4); if (((nextop >> 3) & 7) == 5) { - XOR(x7, x6, x7); // toggle only if bit was 0 - XOR(x4, x4, x7); + AMOOR_W(x6, x5, x2, 1, 1); } else if (((nextop >> 3) & 7) == 6) { - XOR(x4, x4, x7); // toggle only if bit was 1 + XORI(x5, x5, -1); + AMOAND_W(x6, x5, x2, 1, 1); } else { - XOR(x4, x4, x6); // always toggle + AMOXOR_W(x6, x5, x2, 1, 1); } - SCxw(x1, x4, x3, 1, 1); - BNEZ_MARKLOCK(x1); + SRL(x6, x6, x4); + ANDI(x6, x6, 1); + ANDI(xFlags, xFlags, ~1); + OR(xFlags, xFlags, x6); } } break; @@ -474,6 +508,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("LOCK CMPXCHG8B Gq, Eq"); SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION); SET_DFNONE(); + MARKREGd(xRAX); + MARKREGd(xRDX); nextop = F8; addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0); ANDI(xFlags, xFlags, ~(1 << F_ZF)); @@ -515,6 +551,10 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 1: INST_NAME("LOCK CMPXCHG16B Gq, Eq"); + MARKREGsd(xRAX); + MARKREGsd(xRDX); + MARKREGs(xRBX); + MARKREGs(xRCX); static int warned = 0; PASS3(if (!warned) dynarec_log(LOG_INFO, "Warning, LOCK CMPXCHG16B is not well supported on RISC-V and issues are expected.\n")); PASS3(warned = 1); @@ -591,12 +631,12 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni B_MARK3_nocond; MARK; SLLI(x3, x3, 3); - ADDI(x4, xZR, 0xff); ANDI(x1, wback, ~3); // aligning address (into scratch, wback may be a live guest reg) - SLL(x4, x4, x3); // x4 = byte mask - NOT(x5, x4); // x5 = ~mask SLL(x2, x2, x3); // x2 = extented Gb MARK2; + ADDI(x4, xZR, 0xff); // x4 = byte mask (recomputed on SC retry: x4/x5 are clobbered in the loop) + SLL(x4, x4, x3); + NOT(x5, x4); // x5 = ~mask LR_W(x6, x1, 1, 1); // x6 = Ed AND(x7, x6, x4); // x7 = extended Ed.b[dest] AND(x6, x6, x5); // x6 = clear Ed.b[dest] @@ -818,12 +858,12 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); addr = geted(dyn, addr, ninst, nextop, &wback, x5, x1, &fixedaddress, rex, LOCK_LOCK, 0, 1); u8 = F8; - ANDI(x6, xFlags, 1 << F_CF); // carry-in, read once - ADDI(x7, x6, u8); // imm + carry ANDI(x2, wback, 3); SLLI(x2, x2, 3); // offset in bits ANDI(x3, wback, ~3); // aligned addr MARKLOCK; + ANDI(x7, xFlags, 1 << F_CF); // carry-in (recomputed on SC retry: x7 is clobbered in the loop) + ADDI(x7, x7, u8); // imm + carry LR_W(x4, x3, 1, 1); SRL(x6, x4, x2); ANDI(x6, x6, 0xFF); // x6 = old byte @@ -883,12 +923,12 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); addr = geted(dyn, addr, ninst, nextop, &wback, x5, x1, &fixedaddress, rex, LOCK_LOCK, 0, 1); u8 = F8; - ANDI(x6, xFlags, 1 << F_CF); // borrow-in, read once - ADDI(x7, x6, u8); // imm + borrow ANDI(x2, wback, 3); SLLI(x2, x2, 3); // offset in bits ANDI(x3, wback, ~3); // aligned addr MARKLOCK; + ANDI(x7, xFlags, 1 << F_CF); // borrow-in (recomputed on SC retry: x7 is clobbered in the loop) + ADDI(x7, x7, u8); // imm + borrow LR_W(x4, x3, 1, 1); SRL(x6, x4, x2); ANDI(x6, x6, 0xFF); // x6 = old byte @@ -1264,7 +1304,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni *ok = 0; } else { INST_NAME("LOCK XCHG Ed, Gd"); - GETGD; + GETGDsd; addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); ANDI(x1, wback, (1 << (rex.w + 2)) - 1); BNEZ_MARK3(x1); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 7d402778a..c5cc7934c 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -93,22 +93,24 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSD(v0); GETED(0); + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x6, x4); if (rex.w) { - FCVTDL(v0, ed, RD_RNE); + FCVTDL(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); } else { - FCVTDW(v0, ed, RD_RNE); + FCVTDW(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); } + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); break; case 0x2C: INST_NAME("CVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSD(v0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // reset all bits } FCVTLDxw(gd, v0, RD_RTZ); - if (!rex.w) ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); @@ -123,14 +125,14 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2D: INST_NAME("CVTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSD(v0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // // reset all bits } u8 = sse_setround(dyn, ninst, x2, x3); FCVTLDxw(gd, v0, RD_DYN); - if (!rex.w) ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); x87_restoreround(dyn, ninst, u8); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit @@ -149,37 +151,63 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xF0: // CRC32 Gd, Eb INST_NAME("CRC32 Gd, Eb"); + UP32_WRITE32(gd); nextop = F8; GETEB(x1, 0); GETGD; MV(x5, ed); - ZEROUP(gd); - XOR(gd, gd, x5); - MOV32w(x2, 0x82f63b78); - for (int i = 0; i < 8; i++) { - SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); - ANDI(x6, (i & 1) ? x4 : gd, 1); - BEQZ(x6, 4 + 4); - XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + if (cpuext.zbc) { + ZEROUP(gd); + XOR(x5, x5, gd); + SLLI(x5, x5, 56); + MOV64xs(x2, 0x4869EC38DEA713F1ULL, x3); + CLMUL(x5, x5, x2); + MOV64x(x2, 0x105EC76F1ULL); + CLMULH(x5, x5, x2); + SRLI(gd, gd, 8); + XOR(gd, x5, gd); + } else { + if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); + XOR(gd, gd, x5); + MOV32w(x2, 0x82f63b78); + for (int i = 0; i < 8; i++) { + SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); + ANDI(x6, (i & 1) ? x4 : gd, 1); + BEQZ(x6, 4 + 4); + XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + } } break; case 0xF1: // CRC32 Gd, Ed INST_NAME("CRC32 Gd, Ed"); + UP32_WRITE32(gd); nextop = F8; GETGD; GETED(0); MV(x5, ed); - ZEROUP(gd); - MOV32w(x2, 0x82f63b78); - for (int j = 0; j < 4 * (rex.w + 1); ++j) { - SRLI(x3, x5, 8 * j); - ANDI(x3, x3, 0xFF); - XOR(gd, gd, x3); - for (int i = 0; i < 8; i++) { - SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); - ANDI(x6, (i & 1) ? x4 : gd, 1); - BEQZ(x6, 4 + 4); - XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + if (cpuext.zbc) { + if (!rex.w) ZEROUP(x5); + ZEROUP(gd); + XOR(x5, x5, gd); + if (!rex.w) SLLI(x5, x5, 32); + MOV64xs(x2, 0x4869EC38DEA713F1ULL, x3); + CLMUL(x5, x5, x2); + MOV64x(x2, 0x105EC76F1ULL); + CLMULH(x5, x5, x2); + MV(gd, x5); + } else { + if (NEED_ZEROUP32(gd)) ZEROUP_RESULT(gd); + MOV32w(x2, 0x82f63b78); + for (int j = 0; j < 4 * (rex.w + 1); ++j) { + SRLI(x3, x5, 8 * j); + ANDI(x3, x3, 0xFF); + XOR(gd, gd, x3); + for (int i = 0; i < 8; i++) { + SRLI((i & 1) ? gd : x4, (i & 1) ? x4 : gd, 1); + ANDI(x6, (i & 1) ? x4 : gd, 1); + BEQZ(x6, 4 + 4); + XOR((i & 1) ? gd : x4, (i & 1) ? gd : x4, x2); + } } } break; @@ -297,7 +325,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SRLI(x4, x4, 29); MOV32w(x5, 0x007fffff); AND(x4, x4, x5); - LUI(x5, 0x7fc00); + MOV32w(x5, 0x7FC00000); OR(x4, x4, x5); OR(x4, x4, x6); FMVWX(v0, x4); @@ -338,15 +366,9 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSD(v0); GETEXSD(v1, 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v1, v0); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v0, v1); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; break; case 0x5E: INST_NAME("DIVSD Gx, Ex"); @@ -382,15 +404,9 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSD(v0); GETEXSD(v1, 0); - FEQD(x2, v0, v0); - FEQD(x3, v1, v1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, v0, v1); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, v1, v0); + BNEZ(x2, 8); FMVD(v0, v1); - MARK2; break; case 0x70: // TODO: Optimize this! INST_NAME("PSHUFLW Gx, Ex, Ib"); @@ -759,7 +775,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FCVTLD(x3, d0, RD_DYN); SEXT_W(x5, x3); BEQ(x5, x3, 8); - LUI(x3, 0x80000); // INT32_MIN + MOV64x(x3, (int64_t)INT32_MIN); // INT32_MIN SW(x3, gback, gdoffset + 4 * i); } x87_restoreround(dyn, ninst, u8); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c index 8ab7ef44e..1005296dd 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f_vector.c @@ -117,14 +117,19 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x3, VECTOR_SEW64, 1); GETGX_vector(v0, 1, VECTOR_SEW64); GETED(0); - FCVTDL(v0, ed, RD_RNE); } else { SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); GETGX_vector(v0, 1, VECTOR_SEW32); GETED(0); - FCVTDW(v0, ed, RD_RNE); + } + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x5, x6); + if (rex.w) { + FCVTDL(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); + } else { + FCVTDW(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); SET_ELEMENT_WIDTH(x3, VECTOR_SEW64, 1); } + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); if (cpuext.xtheadvector) { v1 = fpu_get_scratch(dyn); VFMV_S_F(v1, v0); @@ -137,7 +142,7 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2C: INST_NAME("CVTTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); if (MODREG) { v0 = sse_get_reg_vector(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0, dyn->vector_eew); @@ -170,7 +175,7 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2D: INST_NAME("CVTSD2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); if (MODREG) { v0 = sse_get_reg_vector(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0, dyn->vector_eew); @@ -223,8 +228,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); } if (BOX64ENV(dynarec_fastnan)) { - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFSQRT_V(v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFSQRT_V(v0, v1, VECTOR_UNMASKED); } else { d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); @@ -257,8 +262,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFADD_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFADD_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x59: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -276,8 +281,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFMUL_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFMUL_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5A: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -338,8 +343,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFSUB_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFSUB_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5D: INST_NAME("MINSD Gx, Ex"); @@ -356,25 +361,21 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } + if (cpuext.xtheadvector) { d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); VFMV_F_S(d0, v0); VFMV_F_S(d1, v1); - FEQD(x2, d0, d0); - FEQD(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, d0, d1); + BNEZ(x2, 8); FMVD(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); // implies VMASK + } else { + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VMFLT_VV(VMASK, v0, v1, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x5E: @@ -393,8 +394,8 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } - VECTOR_LOAD_VMASK(0b01, x4, 1); - VFDIV_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VFDIV_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5F: INST_NAME("MAXSD Gx, Ex"); @@ -411,25 +412,21 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW64); } + if (cpuext.xtheadvector) { d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); VFMV_F_S(d0, v0); VFMV_F_S(d1, v1); - FEQD(x2, d0, d0); - FEQD(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLED(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; + FLTD(x2, d1, d0); + BNEZ(x2, 8); FMVD(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); // implies VMASK + } else { + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW64); + VMFLT_VV(VMASK, v1, v0, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x70: @@ -443,17 +440,17 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i d1 = fpu_get_scratch(dyn); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); tmp64u0 = 0x0007000600050004ULL; - MOV64x(x5, tmp64u0); + MOV64xs(x5, tmp64u0, x3); VMV_S_X(d1, x5); tmp64u0 = ((((uint64_t)u8 >> 6) & 3) << 48) | ((((uint64_t)u8 >> 4) & 3) << 32) | (((u8 >> 2) & 3) << 16) | (u8 & 3); - MOV64x(x5, tmp64u0); - VSLIDE1UP_VX(d0, d1, x5, VECTOR_UNMASKED); + MOV64xs(x5, tmp64u0, x3); + VSLIDE1UP_VX_SAFE(d0, d1, x5, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); if (v0 == v1) { v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VRGATHER_VV(v0, v1, d0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, d0, VECTOR_UNMASKED); break; case 0x7C: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -468,13 +465,45 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_V_V(v0, q0); if (q1 & 1) VMV_V_V(d1, q1); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); - VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); ADDI(x4, xZR, 32); VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); VFADD_VV(q0, d1, d0, VECTOR_UNMASKED); break; + case 0x7D: + INST_NAME("HSUBPS Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1); + GETGX_vector(q0, 1, VECTOR_SEW32); + GETEX_vector(q1, 0, 0, VECTOR_SEW32); + v0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d1 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + d0 = fpu_get_scratch_lmul(dyn, VECTOR_LMUL2); + VMV_V_V(v0, q0); + if (q1 & 1) VMV_V_V(d1, q1); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL2, 2); + VSLIDEUP_VI_SAFE(v0, (q1 & 1) ? d1 : q1, 4, VECTOR_UNMASKED); + vector_vsetvli(dyn, ninst, x1, VECTOR_SEW32, VECTOR_LMUL1, 1); + ADDI(x4, xZR, 32); + VNSRL_WX(d0, v0, xZR, VECTOR_UNMASKED); // first of each pair + VNSRL_WX(d1, v0, x4, VECTOR_UNMASKED); // second of each pair + VFSUB_VV(q0, d0, d1, VECTOR_UNMASKED); + if (!BOX64ENV(dynarec_fastnan)) { + MOV32w(x5, 0x80000000); + VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED); + VMNAND_MM(VMASK, VMASK, VMASK); + VOR_VX(q0, q0, x5, VECTOR_MASKED); + MOV32w(x5, 0x00400000); + VMFNE_VV(VMASK, d1, d1, VECTOR_UNMASKED); // isnan(second), on the original value + VOR_VX(d1, d1, x5, VECTOR_UNMASKED); // quiet(second) + VMERGE_VVM(q0, q0, d1); // second is NaN -> quiet(second) + VMFNE_VV(VMASK, d0, d0, VECTOR_UNMASKED); // isnan(first), on the original value + VOR_VX(d0, d0, x5, VECTOR_UNMASKED); // quiet(first) + VMERGE_VVM(q0, q0, d0); // first is NaN -> quiet(first), priority + } + break; case 0xC2: INST_NAME("CMPSD Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c index 0d24c933c..e6307bde0 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f.c @@ -134,18 +134,19 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2C: INST_NAME("CVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSS(d0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // // reset all bits } FCVTSxw(gd, d0, RD_RTZ); - if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) + ZEROUP_RESULT(gd); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); CBZ_NEXT(x5); + emit_mxcsr_raise_invalid(x5); if (rex.w) { MOV64x(gd, 0x8000000000000000LL); } else { @@ -156,7 +157,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x2D: INST_NAME("CVTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; GETEXSS(d0, 0); if (!BOX64ENV(dynarec_fastround)) { FSFLAGSI(0); // // reset all bits @@ -164,12 +165,13 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int u8 = sse_setround(dyn, ninst, x5, x6); FCVTSxw(gd, d0, RD_DYN); x87_restoreround(dyn, ninst, u8); - if (!rex.w) - ZEROUP(gd); + if (NEED_ZEROUP(gd)) + ZEROUP_RESULT(gd); if (!BOX64ENV(dynarec_fastround)) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); CBZ_NEXT(x5); + emit_mxcsr_raise_invalid(x5); if (rex.w) { MOV64x(gd, 0x8000000000000000LL); } else { @@ -221,7 +223,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FEQS(x5, v1, v1); BNEZ_MARK(x5); BNEZ_MARK2(x4); - LUI(x5, 0x00400); + MOV32w(x5, 0x400000); OR(x3, x3, x5); FMVWX(v1, x3); B_MARK_nocond; @@ -237,7 +239,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETGXSS_empty(v1); q0 = fpu_get_scratch(dyn); // 1.0f d0 = fpu_get_scratch(dyn); // 0.0f - LUI(x3, 0x3F800); // 1.0f + MOV32w(x3, 0x3F800000); FMVWX(q0, x3); if (!BOX64ENV(dynarec_fastnan)) { MOV32w(x6, 0x00400000); @@ -271,7 +273,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEXSS(v0, 0); GETGXSS_empty(v1); q0 = fpu_get_scratch(dyn); - LUI(x3, 0x3F800); // 1.0f + MOV32w(x3, 0x3F800000); FMVWX(q0, x3); if (!BOX64ENV(dynarec_fastnan)) { MOV32w(x6, 0x00400000); @@ -387,6 +389,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF)); BEQZ_MARKi(x5, i); + emit_mxcsr_raise_invalid(x5); MOV32w(x3, 0x80000000); MARKi(i); } @@ -425,15 +428,9 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSS(d0); GETEXSS(d1, 0); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d0, d1); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; break; case 0x5E: INST_NAME("DIVSS Gx, Ex"); @@ -467,15 +464,9 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; GETGXSS(d0); GETEXSS(d1, 0); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d1, d0); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; break; case 0x6F: INST_NAME("MOVDQU Gx,Ex"); @@ -573,6 +564,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("RDFSBASE"); } ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGd(ed); int seg = _FS + ((nextop >> 3) & 7); grab_segdata(dyn, addr, ninst, x4, seg); MVxw(ed, x4); @@ -591,6 +583,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("WRFSBASE"); } ed = TO_NAT((nextop & 7) + (rex.b << 3)); + MARKREGs(ed); int seg = _FS + ((nextop >> 3) & 7) - 2; if (!rex.w) { ZEXTW2(x4, ed); @@ -620,7 +613,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); nextop = F8; GETED(0); - GETGD; + GETGDsd; if (!rex.w && MODREG) { ZEXTW2(x4, ed); ed = x4; @@ -635,22 +628,14 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int CPOPxw(gd, ed); } else { if (rex.w) { - // x7 = 0x5555555555555555 - LUI(x7, 0x55555); - ADDIW(x7, x7, 0x555); - SLLI(x6, x7, 32); - ADD(x7, x7, x6); + MOV64xs(x7, 0x5555555555555555ULL, x6); // v = v - ((v >> 1) & x7) SRLI(x5, ed, 1); AND(x5, x5, x7); SUB(x5, ed, x5); - // x3 = 0x3333333333333333 - LUI(x3, 0x33333); - ADDIW(x3, x3, 0x333); - SLLI(x6, x3, 32); - ADD(x3, x3, x6); + MOV64xs(x3, 0x3333333333333333ULL, x6); // v = (v & x3) + ((v >> 2) & x3); SRLI(x7, x5, 2); @@ -658,39 +643,27 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(x5, x5, x3); ADD(x5, x5, x7); - // x3 = 0x0F0F0F0F0F0F0F0F - LUI(x3, 0xF0F1); - ADDIW(x3, x3, 0xF0F); - SLLI(x6, x3, 32); - ADD(x3, x3, x6); + MOV64xs(x3, 0x0F0F0F0F0F0F0F0FULL, x6); // v = (v + (v >> 4) & x3) SRLI(x7, x5, 4); ADD(x5, x5, x7); AND(x5, x5, x3); - // x3 = 0x0101010101010101 - LUI(x3, 0x1010); - ADDIW(x3, x3, 0x101); - SLLI(x6, x3, 32); - ADD(x3, x3, x6); + MOV64xs(x3, 0x0101010101010101ULL, x6); // count = (v * x3) >> 56 MUL(gd, x5, x3); SRLI(gd, gd, 56); } else { - // x7 = 0x55555555uLL - LUI(x7, 0x55555); - ADDIW(x7, x7, 0x555); + MOV32w(x7, 0x55555555); // v = v - ((v >> 1) & x7) SRLI(x5, ed, 1); AND(x5, x5, x7); SUB(x5, ed, x5); - // x3 = 0x33333333uLL - LUI(x3, 0x33333); - ADDIW(x3, x3, 0x333); + MOV32w(x3, 0x33333333); // v = (v & x3) + ((v >> 2) & x3); SRLI(x7, x5, 2); @@ -698,18 +671,14 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(x5, x5, x3); ADD(x5, x5, x7); - // x3 = 0x0F0F0F0FuLL - LUI(x3, 0xF0F1); - ADDIW(x3, x3, 0xF0F); + MOV32w(x3, 0x0F0F0F0F); // v = (v + (v >> 4) & x3) SRLI(x7, x5, 4); ADD(x5, x5, x7); AND(x5, x5, x3); - // x3 = 01010101uLL - LUI(x3, 0x1010); - ADDIW(x3, x3, 0x101); + MOV32w(x3, 0x01010101); // count = (v * x3) >> 24 MULW(gd, x5, x3); @@ -727,7 +696,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); nextop = F8; GETED(0); - GETGD; + GETGDsd; CLEAR_FLAGS(); if (!rex.w && MODREG) { ZEXTW2(x4, ed); @@ -752,7 +721,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SET_DFNONE(); nextop = F8; GETED(0); - GETGD; + GETGDsd; CLEAR_FLAGS(); if (!rex.w && MODREG) { ZEXTW2(x4, ed); @@ -853,7 +822,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; READFLAGS(X_OF); SETFLAGS(X_OF, SF_SUBSET, NAT_FLAGS_NOFUSION); - GETGD; + GETGDsd; GETED(0); BEXTI(x3, xFlags, F_OF2); IFX (X_OF) { @@ -878,7 +847,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } else { ADDxw(x5, gd, ed); ADDxw(gd, x5, x3); - if (!rex.w) ZEROUP(gd); + if (NEED_ZEROUP(gd)) ZEROUP_RESULT(gd); } break; default: diff --git a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c index a95ce2cd7..37512bfc3 100644 --- a/src/dynarec/rv64/dynarec_rv64_f30f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_f30f_vector.c @@ -143,14 +143,19 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i SET_ELEMENT_WIDTH(x3, VECTOR_SEW64, 1); GETGX_vector(v0, 1, VECTOR_SEW64); GETED(0); - FCVTSL(v0, ed, RD_RNE); - SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); } else { SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); GETGX_vector(v0, 1, VECTOR_SEW32); GETED(0); - FCVTSW(v0, ed, RD_RNE); } + if (!BOX64ENV(dynarec_fastround)) u8 = sse_setround(dyn, ninst, x5, x6); + if (rex.w) { + FCVTSL(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); + SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); + } else { + FCVTSW(v0, ed, !BOX64ENV(dynarec_fastround) ? RD_DYN : RD_RNE); + } + if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8); if (cpuext.xtheadvector) { v1 = fpu_get_scratch(dyn); VFMV_S_F(v1, v0); @@ -163,7 +168,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2C: INST_NAME("CVTTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -189,7 +194,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i case 0x2D: INST_NAME("CVTSS2SI Gd, Ex"); nextop = F8; - GETGD; + GETGDd; SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); if (MODREG) { ed = (nextop & 7) + (rex.b << 3); @@ -232,8 +237,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFSQRT_V(v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFSQRT_V(v0, v1, VECTOR_UNMASKED); break; case 0x52: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -251,11 +256,11 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); FMVWX(v1, x4); // 1.0f - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFSQRT_V(v0, v1, VECTOR_MASKED); - VFRDIV_VF(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFSQRT_V(v0, v1, VECTOR_UNMASKED); + VFRDIV_VF(v0, v0, v1, VECTOR_UNMASKED); break; case 0x53: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -273,7 +278,7 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - LUI(x4, 0x3f800); + MOV32w(x4, 0x3F800000); FMVWX(v1, x4); // 1.0f VECTOR_LOAD_VMASK(0b0001, x4, 1); VFRDIV_VF(v0, v1, v1, VECTOR_MASKED); @@ -294,8 +299,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFADD_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFADD_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x59: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -313,8 +318,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFMUL_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFMUL_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5A: if (!BOX64ENV(dynarec_fastnan)) return 0; @@ -375,8 +380,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFSUB_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFSUB_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5D: INST_NAME("MINSS Gx, Ex"); @@ -393,25 +398,21 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } + if (cpuext.xtheadvector) { d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); VFMV_F_S(d0, v0); VFMV_F_S(d1, v1); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d1, d0); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d0, d1); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); + } else { + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VMFLT_VV(VMASK, v0, v1, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x5E: @@ -430,8 +431,8 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VFDIV_VV(v0, v0, v1, VECTOR_MASKED); + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VFDIV_VV(v0, v0, v1, VECTOR_UNMASKED); break; case 0x5F: INST_NAME("MAXSS Gx, Ex"); @@ -448,25 +449,21 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i VMV_S_X(v1, x4); GETGX_vector(v0, 1, VECTOR_SEW32); } + if (cpuext.xtheadvector) { d0 = fpu_get_scratch(dyn); d1 = fpu_get_scratch(dyn); VFMV_F_S(d0, v0); VFMV_F_S(d1, v1); - FEQS(x2, d0, d0); - FEQS(x3, d1, d1); - AND(x2, x2, x3); - BEQ_MARK(x2, xZR); - FLES(x2, d0, d1); - BEQ_MARK2(x2, xZR); - MARK; + FLTS(x2, d1, d0); + BNEZ(x2, 8); FMVS(d0, d1); - MARK2; - if (cpuext.xtheadvector) { - VFMV_S_F(d0, d0); - VECTOR_LOAD_VMASK(0b0001, x4, 1); - VMERGE_VVM(v0, v0, d0); // implies VMASK - } else { - VFMV_S_F(v0, d0); + VFMV_S_F(d0, d0); + VECTOR_LOAD_VMASK(0b0001, x4, 1); + VMERGE_VVM(v0, v0, d0); // implies VMASK + } else { + SET_SCALAR_FP_WIDTH(x1, VECTOR_SEW32); + VMFLT_VV(VMASK, v1, v0, VECTOR_UNMASKED); + VMERGE_VVM(v0, v1, v0); } break; case 0x6F: @@ -499,17 +496,17 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1); tmp64u0 = ((((uint64_t)u8 >> 6) & 3) << 48) | ((((uint64_t)u8 >> 4) & 3) << 32) | (((u8 >> 2) & 3) << 16) | (u8 & 3); tmp64u0 += 0x0004000400040004ULL; - MOV64x(x5, tmp64u0); + MOV64xs(x5, tmp64u0, x3); VMV_S_X(d1, x5); tmp64u0 = 0x0003000200010000ULL; MOV64x(x5, tmp64u0); - VSLIDE1UP_VX(d0, d1, x5, VECTOR_UNMASKED); + VSLIDE1UP_VX_SAFE(d0, d1, x5, VECTOR_UNMASKED); vector_vsetvli(dyn, ninst, x1, VECTOR_SEW16, VECTOR_LMUL1, 1); if (v0 == v1) { v1 = fpu_get_scratch(dyn); VMV_V_V(v1, v0); } - VRGATHER_VV(v0, v1, d0, VECTOR_UNMASKED); + VRGATHER_VV_SAFE(v0, v1, d0, VECTOR_UNMASKED); break; case 0x7E: INST_NAME("MOVQ Gx, Ex"); diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c index 399b5c6cd..a5ae005c7 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.c +++ b/src/dynarec/rv64/dynarec_rv64_functions.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -30,17 +29,11 @@ #include "gdbjit.h" #include "perfmap.h" -#define XMM0 0 -#define X870 XMM0 + 16 -#define EMM0 XMM0 + 16 - static int fpu_scratch_vreg(int n) { if (n < 7) return SCRATCH0 + n; - if (n < 13) - return 26 + (n - 7); - return ((n - 13) & 1) + 1; + abort(); } // Get a FPU scratch reg @@ -69,6 +62,7 @@ int fpu_get_scratch_lmul(dynarec_rv64_t* dyn, int lmul) void fpu_reset_scratch(dynarec_rv64_t* dyn) { dyn->e.fpu_scratch = 0; + dyn->pending_zero_flushed = 0; } // Get a x87 double reg int fpu_get_reg_x87(dynarec_rv64_t* dyn, int t, int n) @@ -79,6 +73,7 @@ int fpu_get_reg_x87(dynarec_rv64_t* dyn, int t, int n) dyn->e.fpuused[i] = 1; dyn->e.extcache[i].n = n; dyn->e.extcache[i].t = t; + dyn->e.extcache[i].y = 0; dyn->e.news |= (1 << i); return EXTREG(i); // return a Dx } @@ -99,6 +94,7 @@ int fpu_get_reg_emm(dynarec_rv64_t* dyn, int t, int emm) dyn->e.fpuused[i] = 1; dyn->e.extcache[i].t = t; dyn->e.extcache[i].n = emm; + dyn->e.extcache[i].y = 0; dyn->e.news |= (1 << (i)); return EXTREG(i); } @@ -110,6 +106,7 @@ int fpu_get_reg_xmm(dynarec_rv64_t* dyn, int t, int xmm) dyn->e.fpuused[i] = 1; dyn->e.extcache[i].t = t; dyn->e.extcache[i].n = xmm; + dyn->e.extcache[i].y = 0; dyn->e.news |= (1 << i); return EXTREG(i); } @@ -121,6 +118,7 @@ static void fpu_reset_reg_extcache(dynarec_rv64_t* dyn, extcache_t* e) e->extcache[i].v = 0; } dyn->vector_sew = VECTOR_SEWNA; + dyn->vtype_restore = VECTOR_SEWNA; } void fpu_reset_reg(dynarec_rv64_t* dyn) { @@ -373,7 +371,7 @@ int fpuCacheNeedsTransform(dynarec_rv64_t* dyn, int ninst) // if the barrier as already been apply, no transform needed return ((dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) ? 0 : (isCacheEmpty(dyn, ninst) ? 0 : 1); int ret = 0; - if (!i2) { // just purge + if (!i2) { // restore the state the first instruction was emitted with if (dyn->insts[ninst].e.stack_next) { return 1; } @@ -386,6 +384,9 @@ int fpuCacheNeedsTransform(dynarec_rv64_t* dyn, int ninst) && dyn->insts[ninst].e.extcache[i].n < dyn->insts[ninst].e.stack_pop)) ret = 1; } + for (int i = 0; i < 24 && !ret; ++i) + if (dyn->insts[0].e.extcache[i].v) + ret = 1; return ret; } // Check if ninst can be compatible to i2 @@ -403,6 +404,7 @@ int fpuCacheNeedsTransform(dynarec_rv64_t* dyn, int ninst) if (dyn->insts[ninst].e.extcache[i].n != cache_i2.extcache[i].n) { // not the same x64 reg ret = 1; } else if (dyn->insts[ninst].e.extcache[i].t == EXT_CACHE_XMMR && cache_i2.extcache[i].t == EXT_CACHE_XMMW) { /* nothing */ + } else if (dyn->insts[ninst].e.extcache[i].t == EXT_CACHE_YMMR && cache_i2.extcache[i].t == EXT_CACHE_YMMW) { /* nothing */ } else ret = 1; } @@ -428,6 +430,19 @@ int sewNeedsTransform(dynarec_rv64_t* dyn, int ninst) void extcacheUnwind(extcache_t* cache) { + if (!cache->swapped && !cache->news && !cache->stack_push && !cache->stack_pop) { + int dirty = 0; + for (int i = 0; i < 16; ++i) + if (cache->olds[i].changed || cache->olds[i].purged) { + dirty = 1; + break; + } + if (!dirty) { + cache->barrier = 0; + cache->fpu_scratch = 0; + return; + } + } if (cache->swapped) { // unswap int a = -1; @@ -538,9 +553,13 @@ void extcacheUnwind(extcache_t* cache) break; case EXT_CACHE_XMMR: case EXT_CACHE_XMMW: + case EXT_CACHE_YMMR: + case EXT_CACHE_YMMW: cache->ssecache[cache->extcache[i].n].reg = EXTREG(i); cache->ssecache[cache->extcache[i].n].vector = 1; - cache->ssecache[cache->extcache[i].n].write = (cache->extcache[i].t == EXT_CACHE_XMMW) ? 1 : 0; + cache->ssecache[cache->extcache[i].n].write = (cache->extcache[i].t == EXT_CACHE_XMMW || cache->extcache[i].t == EXT_CACHE_YMMW) ? 1 : 0; + cache->ssecache[cache->extcache[i].n].ymm = (cache->extcache[i].t == EXT_CACHE_YMMR || cache->extcache[i].t == EXT_CACHE_YMMW) ? 1 : cache->extcache[i].y; + cache->ssecache[cache->extcache[i].n].ymm0 = (cache->ymm0 >> cache->extcache[i].n) & 1; break; case EXT_CACHE_ST_F: case EXT_CACHE_ST_D: @@ -558,6 +577,7 @@ void extcacheUnwind(extcache_t* cache) cache->fpuused[i] = 0; } } + sse_sync_all_cache_types(cache); } // will go badly if address is unaligned @@ -627,6 +647,8 @@ const char* getCacheName(int t, int n) case EXT_CACHE_SCR: sprintf(buff, "Scratch"); break; case EXT_CACHE_XMMW: sprintf(buff, "XMM%d", n); break; case EXT_CACHE_XMMR: sprintf(buff, "xmm%d", n); break; + case EXT_CACHE_YMMW: sprintf(buff, "YMM%d", n); break; + case EXT_CACHE_YMMR: sprintf(buff, "ymm%d", n); break; case EXT_CACHE_NONE: buff[0] = '\0'; break; } return buff; @@ -715,7 +737,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r } if (!dyn->need_dump && !BOX64ENV(dynarec_gdbjit) && !BOX64ENV(dynarec_perf_map)) return; - static char buf[4096]; + static char buf[65536]; int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s), set=%X/%X, use=%X, need=%X/%X, fuse=%d/%d, sm=%d(%d/%d), sew@entry=%d, sew@exit=%d", dyn->insts[ninst].x64.barrier, dyn->insts[ninst].x64.state_flags, @@ -753,6 +775,8 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r case EXT_CACHE_SD: length += sprintf(buf + length, " f%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_XMMR: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_XMMW: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; + case EXT_CACHE_YMMR: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; + case EXT_CACHE_YMMW: length += sprintf(buf + length, " v%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_SCR: length += sprintf(buf + length, " f%d:%s", EXTREG(ii), getCacheName(dyn->insts[ninst].e.extcache[ii].t, dyn->insts[ninst].e.extcache[ii].n)); break; case EXT_CACHE_NONE: default: break; @@ -855,27 +879,46 @@ int fpu_is_st_freed(dynarec_rv64_t* dyn, int ninst, int st) return (dyn->e.tags & (0b11 << (st * 2))) ? 1 : 0; } +static int hasLinearPredecessor(const dynarec_rv64_t* dyn, int ninst); + void updateNativeFlags(dynarec_rv64_t* dyn) { if (!BOX64ENV(dynarec_nativeflags)) return; - for (int i = 1; i < dyn->size; ++i) + for (int i = 0; i < dyn->size; ++i) if (dyn->insts[i].nat_flags_fusion) { int j = i - 1; int found = 0; - if (dyn->insts[i].pred_sz == 1 && dyn->insts[i].pred[0] == j) { + int last_fused = 0; + if (hasLinearPredecessor(dyn, i)) { while (j >= 0) { if (dyn->insts[j].x64.set_flags && (dyn->insts[i].x64.use_flags & dyn->insts[j].x64.set_flags) == dyn->insts[i].x64.use_flags) { + int needsign = (dyn->insts[i].x64.use_flags & X_SF) ? 1 : 0; + int needunsigned = (dyn->insts[i].x64.use_flags & X_CF) ? 1 : 0; + if (dyn->insts[j].nat_flags_fusion && ((needsign && dyn->insts[j].nat_flags_needunsigned) || (needunsigned && dyn->insts[j].nat_flags_needsign))) + break; // not compatible, stop here dyn->insts[j].nat_flags_fusion = 1; - if (dyn->insts[i].x64.use_flags & X_SF) { + if (needsign) dyn->insts[j].nat_flags_needsign = 1; - } + if (needunsigned) + dyn->insts[j].nat_flags_needunsigned = 1; dyn->insts[i].x64.use_flags = 0; - dyn->insts[j].nat_next_inst = i; + if (last_fused) { + dyn->insts[last_fused].nat_next_inst = i; + } else { + uint16_t* next = &dyn->insts[j].nat_next_inst; + while (*next) + next = &dyn->insts[*next].nat_next_inst; + *next = i; + } + dyn->insts[i].up32_read |= dyn->insts[j].up32_write32; found = 1; break; - } else if (j && dyn->insts[j].pred_sz == 1 && dyn->insts[j].pred[0] == j - 1 - && dyn->insts[j].no_scratch_usage && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) { + } else if (hasLinearPredecessor(dyn, j) && dyn->insts[j].nat_flags_fusion && dyn->insts[j].x64.jmp && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) { + // already fused Jcc consumer + if (!last_fused) last_fused = j; + j -= 1; + } else if (hasLinearPredecessor(dyn, j) && dyn->insts[j].no_scratch_usage && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) { j -= 1; } else break; @@ -913,3 +956,339 @@ void fpu_unwind_restore(dynarec_rv64_t* dyn, int ninst, extcache_t* cache) { memcpy(&dyn->insts[ninst].e, cache, sizeof(extcache_t)); } + +static int hasLinearPredecessor(const dynarec_rv64_t* dyn, int ninst) +{ + return ninst > 0 && dyn->insts[ninst].pred_sz == 1 && dyn->insts[ninst].pred[0] == ninst - 1; +} + +int isUpper32Zero(dynarec_rv64_t* dyn, int ninst, int reg) +{ + if (!IS_GPR(reg)) + return 0; + + const uint16_t bit = (uint16_t)(1 << TO_X64(reg)); + int current = ninst; + for (int depth = 0; depth < 4 && hasLinearPredecessor(dyn, current); ++depth) { + const instruction_rv64_t* prev = &dyn->insts[current - 1]; + if (prev->x64.has_callret || prev->x64.barrier) + return 0; + if (prev->up32_write64 & bit) return prev->up32_zero & bit; + --current; + } + return 0; +} + +static uint32_t getUsedVectorMask(const dynarec_rv64_t* dyn, int first, int last) +{ + uint32_t ret = 0; + for (int i = first; i <= last && i < dyn->size; ++i) + ret |= dyn->insts[i].vec_used; + return ret; +} + +static int getFirstVectorUse(const dynarec_rv64_t* dyn, int first, int last, int reg) +{ + for (int i = first; i <= last && i < dyn->size; ++i) + if (dyn->insts[i].vec_used & (1u << reg)) + return i; + return -1; +} + +static void applyPreloadState(dynarec_rv64_t* dyn, int first, int first_use, int reg) +{ + for (int i = first; i < first_use; ++i) { + extcache_t* e = &dyn->insts[i].e; + sse_cache_t* s = &e->ssecache[reg]; + s->reg = VREG(reg); + s->vector = 1; + s->single = 0; + s->write = 0; + s->ymm = 0; + s->ymm0 = (e->ymm0 >> reg) & 1; + e->fpuused[EXTIDX(VREG(reg))] = 1; + e->extcache[EXTIDX(VREG(reg))].n = reg; + e->extcache[EXTIDX(VREG(reg))].y = 0; + sse_sync_cache_type(e, reg); + } +} + +void updatePreloads(dynarec_rv64_t* dyn) +{ + if (!cpuext.vector) + return; + for (int first = 0; first < dyn->size; ++first) { + if (dyn->insts[first].preload_xmmymm) + continue; + if (first) + break; + if (!dyn->insts[first].pred_sz) + continue; + int last = dyn->size + 1; + for (int j = 0; j < dyn->insts[first].pred_sz; ++j) { + int pred = dyn->insts[first].pred[j]; + if (pred != first - 1 && pred < last) + last = pred; + } + if (last > dyn->size || last <= first) + continue; + if (first && !dyn->insts[first - 1].x64.has_next) + continue; + int straight = 1; + for (int i = first; i < last && straight; ++i) { + const instruction_rv64_t* inst = &dyn->insts[i]; + if (!inst->x64.has_next || (inst->x64.barrier & BARRIER_FLOAT) + || inst->x64.has_callret) + straight = 0; + } + if (!straight) + continue; + uint32_t preload = getUsedVectorMask(dyn, first, last); + if (!preload) + continue; + uint32_t accepted = 0; + for (int reg = 0; reg < 16; ++reg) { + if (!(preload & (1u << reg))) + continue; + int first_use = getFirstVectorUse(dyn, first, last, reg); + if (first_use < 0) + continue; + int ok = 1; + int prev = first - 1; + if (prev >= 0 && dyn->insts[prev].e.ssecache[reg].v != -1) + ok = 0; + for (int i = first; i < first_use && ok; ++i) + if (dyn->insts[i].e.ssecache[reg].v != -1) + ok = 0; + if (ok && dyn->insts[first_use].e.ssecache[reg].v == -1) + ok = 0; + if (!ok) + continue; + applyPreloadState(dyn, first, first_use, reg); + accepted |= 1u << reg; + } + if (accepted) + dyn->insts[first].preload_xmmymm = accepted; + } +} + +void updateUpperLiveness(dynarec_rv64_t* dyn) +{ + int n = dyn->size; + if (n <= 0) + return; + + size_t live_size = (size_t)n * sizeof(uint16_t); + size_t pending_size = (size_t)n * sizeof(uint16_t); + size_t work_size = (size_t)n * sizeof(int); + size_t list_size = (size_t)n * sizeof(uint8_t); + void* buffer = calloc(1, 5 * live_size + pending_size + work_size + list_size); + if (!buffer) + return; + uint16_t* live_in = (uint16_t*)buffer; + uint16_t* live_out = (uint16_t*)((char*)live_in + live_size); + uint16_t* live_ymm_in = (uint16_t*)((char*)live_out + live_size); + uint16_t* live_ymm_out = (uint16_t*)((char*)live_ymm_in + live_size); + uint16_t* pending_in = (uint16_t*)((char*)live_ymm_out + live_size); + uint16_t* pend_ymm = (uint16_t*)((char*)pending_in + pending_size); + int* work = (int*)((char*)pend_ymm + live_size); + uint8_t* on_list = (uint8_t*)((char*)work + work_size); + + for (int i = 0; i < n; ++i) { + instruction_rv64_t* inst = &dyn->insts[i]; + inst->promote_ymm = 0; + if (!inst->x64.alive || inst->pred_sz < 2 || (inst->x64.barrier & BARRIER_FLOAT)) + continue; + const extcache_t* first = &dyn->insts[inst->pred[0]].e; + uint16_t promote = 0; + int need_barrier = 0; + for (int p = 1; p < inst->pred_sz && !need_barrier; ++p) { + const extcache_t* pe = &dyn->insts[inst->pred[p]].e; + uint16_t mask_diff = (uint16_t)(first->ymm0 ^ pe->ymm0); + uint16_t resolved = 0; + for (int r = 0; r < 16; ++r) { + const sse_cache_t* a = &first->ssecache[r]; + const sse_cache_t* b = &pe->ssecache[r]; + int a_cached = (a->v != -1 && a->vector); + int b_cached = (b->v != -1 && b->vector); + if (!a_cached || !b_cached) + continue; + if (a->ymm == b->ymm && a->ymm0 == b->ymm0) + continue; + int a_ok = a->ymm || (!a->ymm && a->ymm0); + int b_ok = b->ymm || (!b->ymm && b->ymm0); + if (a_ok && b_ok) { + if (!a->ymm) promote |= (uint16_t)(1u << r); + if (!b->ymm) promote |= (uint16_t)(1u << r); + resolved |= (uint16_t)(1u << r); + continue; + } + need_barrier = 1; + break; + } + if (mask_diff & (uint16_t)~resolved) + need_barrier = 1; + } + if (need_barrier) + inst->x64.barrier |= BARRIER_FLOAT; + else + inst->promote_ymm = promote; + } + + int sp = 0; + for (int i = n - 1; i >= 0; --i) { + if (dyn->insts[i].x64.alive) { + work[sp++] = i; + on_list[i] = 1; + } + } + // backward analysis + while (sp > 0) { + int i = work[--sp]; + on_list[i] = 0; + const instruction_rv64_t* inst = &dyn->insts[i]; + if (!inst->x64.alive) + continue; + uint16_t combined_out = 0; + if (inst->x64.has_next && i + 1 < n && dyn->insts[i + 1].x64.alive) + combined_out |= live_in[i + 1]; + if (inst->x64.jmp) { + if (inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n) + combined_out |= live_in[inst->x64.jmp_insts]; + else + combined_out = UINT16_MAX; + } + int has_internal_jump = inst->x64.jmp && inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n; + if ((inst->x64.has_next && i == n - 1) || (!inst->x64.has_next && !has_internal_jump)) + combined_out = UINT16_MAX; + live_out[i] = combined_out; + + uint16_t combined_ymm_out = 0; + if (inst->x64.has_next && i + 1 < n && dyn->insts[i + 1].x64.alive) + combined_ymm_out |= live_ymm_in[i + 1]; + if (inst->x64.jmp && inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n) + combined_ymm_out |= live_ymm_in[inst->x64.jmp_insts]; + if ((!inst->x64.has_next && !has_internal_jump) || (inst->x64.jmp && inst->x64.jmp_insts < 0)) + combined_ymm_out = UINT16_MAX; + live_ymm_out[i] = combined_ymm_out; + + uint16_t live_ymm_in_val = inst->ymm_upper_use | (combined_ymm_out & (uint16_t)~inst->ymm_upper_def); + if ((inst->x64.barrier & BARRIER_FLOAT) || inst->x64.has_callret) + live_ymm_in_val = UINT16_MAX; + + uint16_t live_in_val = inst->up32_read | (combined_out & (uint16_t)~inst->up32_write64); + if ((live_in_val != live_in[i]) || (live_ymm_in_val != live_ymm_in[i])) { + live_in[i] = live_in_val; + live_ymm_in[i] = live_ymm_in_val; + for (int p = 0; p < inst->pred_sz; ++p) { + int j = inst->pred[p]; + if (!on_list[j]) { + work[sp++] = j; + on_list[j] = 1; + } + } + } + } + + for (int i = 0; i < n; ++i) { + instruction_rv64_t* inst = &dyn->insts[i]; + inst->up32_skip = inst->up32_write32 & (uint16_t)~live_out[i]; + inst->ymm_upper_live = live_ymm_out[i]; + } + + // forward analysis + memset(pending_in, 0, pending_size); + memset(pend_ymm, 0, live_size); + memset(on_list, 0, list_size); + sp = 0; + for (int i = 0; i < n; ++i) { + if (dyn->insts[i].x64.alive) { + work[sp++] = i; + on_list[i] = 1; + } + } + while (sp > 0) { + int i = work[--sp]; + on_list[i] = 0; + instruction_rv64_t* inst = &dyn->insts[i]; + if (!inst->x64.alive) + continue; + + uint16_t merged_pending = 0; + uint16_t merged_ymm = 0; + for (int p = 0; p < inst->pred_sz; ++p) { + int j = inst->pred[p]; + const instruction_rv64_t* pred = &dyn->insts[j]; + merged_pending |= (pending_in[j] & (uint16_t)~pred->up32_write64) | pred->up32_skip; + uint16_t ymm_def = pred->ymm_pending_materialized ? UINT16_MAX : pred->ymm_upper_def; + merged_ymm |= (pend_ymm[j] & (uint16_t)~ymm_def) | (pred->ymm_zero & pred->ymm_upper_live); + } + if (inst->x64.barrier & BARRIER_FLOAT) merged_ymm = 0; + merged_ymm &= (uint16_t)~inst->promote_ymm; + if ((merged_pending != pending_in[i]) || (merged_ymm != pend_ymm[i])) { + pending_in[i] = merged_pending; + pend_ymm[i] = merged_ymm; + if (inst->x64.has_next && i + 1 < n && dyn->insts[i + 1].x64.alive && !on_list[i + 1]) { + work[sp++] = i + 1; + on_list[i + 1] = 1; + } + if (inst->x64.jmp && inst->x64.jmp_insts >= 0 && inst->x64.jmp_insts < n) { + int j = inst->x64.jmp_insts; + if (dyn->insts[j].x64.alive && !on_list[j]) { + work[sp++] = j; + on_list[j] = 1; + } + } + } + } + for (int i = 0; i < n; ++i) { + dyn->insts[i].up32_pending = pending_in[i]; + dyn->insts[i].ymm_pending = pend_ymm[i]; + } + + free(buffer); +} + +void updateRspMerge(dynarec_rv64_t* dyn, int is32bits) +{ + const int delta = is32bits ? 4 : 8; + int pending = 0; + int last_pushpop = -1; + for (int i = 0; i < dyn->size; ++i) { + instruction_rv64_t* inst = &dyn->insts[i]; + inst->rsp_entry = 0; + inst->rsp_flush = 0; + inst->rsp_merge = 0; + int class = (inst->x64.alive && !BOX64ENV(dynarec_test)) ? inst->rsp_class : RSP_CLASS_BARRIER; + if (pending && (class == RSP_CLASS_BARRIER || (i == 0) || (inst->pred_sz != 1) || (inst->pred[0] != i - 1))) { + dyn->insts[last_pushpop].rsp_flush = pending; + pending = 0; + last_pushpop = -1; + } + switch (class) { + case RSP_CLASS_PUSH: + if (pending - (inst->rsp_span ? inst->rsp_span : delta) < -2048) { + dyn->insts[last_pushpop].rsp_flush = pending; + pending = 0; + } + inst->rsp_entry = pending; + inst->rsp_merge = 1; + pending -= (inst->rsp_span ? inst->rsp_span : delta); + last_pushpop = i; + break; + case RSP_CLASS_POP: + if (pending + (inst->rsp_span ? inst->rsp_span : delta) > 2047) { + dyn->insts[last_pushpop].rsp_flush = pending; + pending = 0; + } + inst->rsp_entry = pending; + inst->rsp_merge = 1; + pending += (inst->rsp_span ? inst->rsp_span : delta); + last_pushpop = i; + break; + default: + break; + } + } + if (pending) dyn->insts[last_pushpop].rsp_flush = pending; +} diff --git a/src/dynarec/rv64/dynarec_rv64_functions.h b/src/dynarec/rv64/dynarec_rv64_functions.h index 5f949ac7b..c59b858ff 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.h +++ b/src/dynarec/rv64/dynarec_rv64_functions.h @@ -7,7 +7,7 @@ typedef struct x64emu_s x64emu_t; typedef struct dynarec_rv64_s dynarec_rv64_t; -#define SCRATCH0 3 +#define SCRATCH0 1 #define VMASK 0 // Get an FPU scratch reg @@ -70,6 +70,10 @@ void fpu_reset_ninst(dynarec_native_t* dyn, int ninst); int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st); void updateNativeFlags(dynarec_rv64_t* dyn); +void updateUpperLiveness(dynarec_rv64_t* dyn); +void updatePreloads(dynarec_rv64_t* dyn); +int isUpper32Zero(dynarec_rv64_t* dyn, int ninst, int reg); +void updateRspMerge(dynarec_rv64_t* dyn, int is32bits); void get_free_scratch(dynarec_rv64_t* dyn, int ninst, uint8_t* tmp1, uint8_t* tmp2, uint8_t* tmp3, uint8_t s1, uint8_t s2, uint8_t s3, uint8_t s4, uint8_t s5); #endif //__DYNAREC_RV64_FUNCTIONS_H__ diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 392b9b17b..9f566ee5d 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -25,6 +25,23 @@ #include "dynarec_rv64_private.h" #include "dynarec_rv64_functions.h" #include "../dynarec_helper.h" +#include "rv64_mov_imm.h" + +typedef struct rv64_mov_dynctx_s { + dynarec_rv64_t* dyn; + int ninst; +} rv64_mov_dynctx_t; + +static void rv64_mov_emit_word(void* p, uint32_t insn) +{ + rv64_mov_dynctx_t* c = (rv64_mov_dynctx_t*)p; + dynarec_rv64_t* dyn = c->dyn; + int ninst = c->ninst; + MAYUSE(dyn); + MAYUSE(ninst); + MAYUSE(insn); + EMIT(insn); +} /* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta) @@ -56,6 +73,8 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t sib = F8; int sib_reg = ((sib >> 3) & 7) + (rex.x << 3); int sib_reg2 = (sib & 0x7) + (rex.b << 3); + if ((sib & 0x7) != 5) UP32_READ(TO_NAT(sib_reg2)); + if (sib_reg != 4) UP32_READ(TO_NAT(sib_reg)); if ((sib & 0x7) == 5) { int64_t tmp = F32S; if (sib_reg != 4) { @@ -173,6 +192,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if (!IS_GPR(ret)) SCRATCH_USAGE(1); } } else { + UP32_READ(TO_NAT((nextop & 7) + (rex.b << 3))); ret = TO_NAT((nextop & 7) + (rex.b << 3)); } } else { @@ -182,6 +202,8 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if ((nextop & 7) == 4) { sib = F8; sib_reg = ((sib >> 3) & 7) + (rex.x << 3); + UP32_READ(TO_NAT((sib & 0x07) + (rex.b << 3))); + if (sib_reg != 4) UP32_READ(TO_NAT(sib_reg)); } int sib_reg2 = (sib & 0x07) + (rex.b << 3); if (nextop & 0x80) @@ -210,8 +232,10 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, } else { ret = TO_NAT(sib_reg2); } - } else + } else { + UP32_READ(TO_NAT((nextop & 0x07) + (rex.b << 3))); ret = TO_NAT((nextop & 0x07) + (rex.b << 3)); + } } else { if (i64 >= -2048 && i64 <= 2047) { if ((nextop & 7) == 4) { @@ -236,6 +260,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if (!IS_GPR(ret)) SCRATCH_USAGE(1); } } else { + UP32_READ(TO_NAT((nextop & 0x07) + (rex.b << 3))); ADDIy(ret, TO_NAT((nextop & 0x07) + (rex.b << 3)), i64); if (!IS_GPR(ret)) SCRATCH_USAGE(1); } @@ -251,6 +276,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, ADDy(ret, tmp, scratch); } } else { + UP32_READ(TO_NAT((nextop & 0x07) + (rex.b << 3))); PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3))); ADDy(ret, tmp, scratch); } @@ -381,7 +407,7 @@ void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -403,7 +429,7 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog_fast); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -417,7 +443,7 @@ void doEnterBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) LD(s1, s1, 0); // load the dynablock pointer ADDI(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, 1); - AMOADD_W(s2, s3, s1, 0, 0); + AMOADD_W(s2, s3, s1, 0, 1); } void doLeaveBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) @@ -429,7 +455,7 @@ void doLeaveBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) LD(s1, s1, 0); // load the dynablock pointer ADDI(s1, s1, offsetof(dynablock_t, in_used)); MOV32w(s3, -1); - AMOADD_W(s2, s3, s1, 0, 0); + AMOADD_W(s2, s3, s1, 0, 1); } #ifdef JMPTABLE_SHIFT4 #error TODO! @@ -513,7 +539,7 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 } CLEARIP(); SMEND(); - if (BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if (BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // #ifdef HAVE_TRACE // The JALR(xRA, ...) form is only for gdb backtraces, but it breaks the @@ -538,8 +564,10 @@ void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) LD(xRA, xSP, 0); // native addr LD(x6, xSP, 8); // x86 addr ADDI(xSP, xSP, 16); // pop - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); + else if (!BOX64DRENV(dynarec_strongmem)) + DMB_TSO(); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); // not the correct return address, regular jump, but purge the stack first, it's unsync now... @@ -552,6 +580,22 @@ void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) CLEARIP(); } +void checkCRC(dynarec_rv64_t* dyn, int ninst) +{ + MAYUSE(ninst); + int delta = -(dyn->native_size + sizeof(void*)); + AUIPC(x6, SPLIT20(delta)); + LD(x6, x6, SPLIT12(delta)); + LD(x3, x6, offsetof(dynablock_t, x64_addr)); + LWU(x4, x6, offsetof(dynablock_t, x64_size)); + TABLE64C(x1, cpuext.zbc ? const_rv64_crc_autocrc_zbc : const_rv64_crc_autocrc); + JALR(xRA, x1); + LWU(x1, x6, offsetof(dynablock_t, hash)); + BEQ(x2, x1, 4 * 4); + TABLE64C(x1, const_native_next_invalid); + JALR(xZR, x1); +} + void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits) { int64_t j64; @@ -605,6 +649,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, { MAYUSE(fnc); CHECK_DFNONE(1); + UP32_READALL(); if (savereg == 0) savereg = x87pc; if (saveflags) { @@ -637,10 +682,8 @@ void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, MV(ret, A0); } - // reinitialize sew, the native function may have changed vtype / vl + // the native function may have changed vtype / vl: force the cache-pop to re-emit it dyn->inst_vl = 0; // force emit, do not rely on tracked state - if (dyn->vector_sew != VECTOR_SEWNA) - vector_vsetvli(dyn, ninst, savereg, dyn->vector_sew, VECTOR_LMUL1, 1); LD(savereg, xSP, 0); ADDI(xSP, xSP, 16); @@ -665,6 +708,11 @@ void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, if (savereg != x87pc && dyn->need_x87check) NATIVE_RESTORE_X87PC(); // SET_NODF(); + // this call can be on a conditional path (for example: IDIV), + // so the vtype is not known at the merge point, let later opcodes emit it again + dyn->vector_sew = VECTOR_SEWNA; + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; CLEARIP(); } @@ -672,6 +720,7 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) { MAYUSE(fnc); CHECK_DFNONE(1); + UP32_READALL(); fpu_pushcache(dyn, ninst, x3, 1); // save RSP in case there are x86 callbacks... SD(xRSP, xEmu, offsetof(x64emu_t, regs[_SP])); @@ -696,14 +745,16 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) } // all done, restore all regs - // reinitialize sew, the native function may have changed vtype / vl + // the native function may have changed vtype / vl: force the cache-pop to re-emit it dyn->inst_vl = 0; // force emit, do not rely on tracked state - if (dyn->vector_sew != VECTOR_SEWNA) - vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1); fpu_popcache(dyn, ninst, x3, 1); NATIVE_RESTORE_X87PC(); // SET_NODF(); + // the call may be on a conditional path (IDIV), so do not assume the vtype is restored + dyn->vector_sew = VECTOR_SEWNA; + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; } void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment) @@ -907,7 +958,7 @@ void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, in if (a > 0) { SLLI(s1, s1, a * 2); } else { - LUI(s3, 0xffff0); + MOV64x(s3, 0xFFFFFFFFFFFF0000); OR(s1, s1, s3); SRLI(s1, s1, -a * 2); } @@ -942,12 +993,7 @@ void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, in #endif ADDI(s3, s2, dyn->e.x87cache[i]); // unadjusted count, as it's relative to real top ANDI(s3, s3, 7); // (emu->top + st)&7 - if (cpuext.zba) - SH3ADD(s1, s3, xEmu); - else { - SLLI(s1, s3, 3); - ADD(s1, xEmu, s1); - } + ADDSL(s1, xEmu, s3, 3, s1); switch (extcache_get_current_st(dyn, ninst, st)) { case EXT_CACHE_ST_D: FSD(dyn->e.x87reg[i], s1, offsetof(x64emu_t, x87)); // save the value @@ -1054,12 +1100,7 @@ static void x87_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int if (dyn->e.x87cache[i] != -1) { ADDI(s3, s2, dyn->e.x87cache[i]); ANDI(s3, s3, 7); // (emu->top + i)&7 - if (cpuext.zba) - SH3ADD(s1, s3, xEmu); - else { - SLLI(s1, s3, 3); - ADD(s1, xEmu, s1); - } + ADDSL(s1, xEmu, s3, 3, s1); if (extcache_get_current_st_f(dyn, dyn->e.x87cache[i]) >= 0) { FCVTDS(SCRATCH0, dyn->e.x87reg[i]); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -1136,12 +1177,7 @@ int x87_get_cache(dynarec_rv64_t* dyn, int ninst, int populate, int s1, int s2, ADDI(s2, s2, a); ANDI(s2, s2, 7); } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); FLD(dyn->e.x87reg[ret], s1, offsetof(x64emu_t, x87)); } MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st); @@ -1188,12 +1224,7 @@ void x87_refresh(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) ADDI(s2, s2, a); ANDI(s2, s2, 7); // (emu->top + i)&7 } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); if (dyn->e.extcache[EXTIDX(reg)].t == EXT_CACHE_ST_F) { FCVTDS(SCRATCH0, reg); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -1231,12 +1262,7 @@ void x87_forget(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) ADDI(s2, s2, a); ANDI(s2, s2, 7); // (emu->top + i)&7 } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); if (dyn->e.extcache[EXTIDX(reg)].t == EXT_CACHE_ST_F) { FCVTDS(SCRATCH0, reg); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -1275,12 +1301,7 @@ void x87_reget_st(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) ADDI(s2, s2, a); AND(s2, s2, 7); } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); FLD(dyn->e.x87reg[i], s1, offsetof(x64emu_t, x87)); MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st); // ok @@ -1300,12 +1321,7 @@ void x87_reget_st(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int st) int a = st - dyn->e.x87stack; ADDI(s2, s2, a); ANDI(s2, s2, 7); // (emu->top + i)&7 - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); FLD(dyn->e.x87reg[ret], s1, offsetof(x64emu_t, x87)); MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st); } @@ -1335,12 +1351,7 @@ void x87_free(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int st) } ANDI(s2, s2, 7); // (emu->top + i)&7 } - if (cpuext.zba) - SH3ADD(s1, s2, xEmu); - else { - SLLI(s2, s2, 3); - ADD(s1, xEmu, s2); - } + ADDSL(s1, xEmu, s2, 3, s2); if (dyn->e.extcache[EXTIDX(reg)].t == EXT_CACHE_ST_F) { FCVTDS(SCRATCH0, reg); FSD(SCRATCH0, s1, offsetof(x64emu_t, x87)); @@ -1484,6 +1495,25 @@ void mmx_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) mmx_flush_reg_preserve_vtype(dyn, ninst, s1, a); } +int fpu_borrow_reg(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int reg) +{ + int idx = EXTIDX(reg); + switch (dyn->e.extcache[idx].t) { + case EXT_CACHE_ST_F: + case EXT_CACHE_ST_D: + case EXT_CACHE_ST_I64: + x87_forget(dyn, ninst, s1, s2, dyn->e.extcache[idx].n); + break; + case EXT_CACHE_MM: + case EXT_CACHE_MMV: + mmx_forget_reg(dyn, ninst, s1, dyn->e.extcache[idx].n); + break; + default: + break; + } + return reg; +} + void mmx_flush_reg_preserve_vtype(dynarec_rv64_t* dyn, int ninst, int s1, int a) { if (dyn->e.mmxcache[a].v == -1) @@ -1654,10 +1684,17 @@ static void mmx_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } +static void sse_mark_used(dynarec_rv64_t* dyn, int ninst, int a) +{ + if (ninst >= 0 && ninst < dyn->size && a >= 0 && a < 16) + dyn->insts[ninst].vec_used |= 1u << a; +} + // SSE / SSE2 helpers // get ext register for a SSE reg, create the entry if needed int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) { + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 1) { // it's in the fpu, forget it first... @@ -1682,6 +1719,8 @@ int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) int ret = dyn->e.ssecache[a].reg; dyn->e.ssecache[a].single = single; dyn->e.ssecache[a].vector = 0; + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); if (dyn->e.ssecache[a].single) FLW(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); else @@ -1692,6 +1731,7 @@ int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) // get ext register for a SSE reg, but don't try to synch it if it needed to be created int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) { + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 1) { // it's in the vpu, forget it first... @@ -1720,6 +1760,8 @@ int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single) dyn->e.ssecache[a].reg = fpu_get_reg_xmm(dyn, single ? EXT_CACHE_SS : EXT_CACHE_SD, a); dyn->e.ssecache[a].single = single; dyn->e.ssecache[a].vector = 0; + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); return dyn->e.ssecache[a].reg; } @@ -1744,6 +1786,8 @@ int sse_get_reg_size_changed(dynarec_rv64_t* dyn, int ninst, int s1, int a, int int ret = dyn->e.ssecache[a].reg; dyn->e.ssecache[a].single = single; dyn->e.ssecache[a].vector = 0; + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); if (!single) // load happens before size changed FLW(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a])); else @@ -1756,6 +1800,7 @@ void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) { if (dyn->e.ssecache[a].v == -1) return; + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].vector == 1) return sse_forget_reg_vector(dyn, ninst, s1, a); if (dyn->e.ssecache[a].single) @@ -1774,6 +1819,9 @@ void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a) // get rvv register for a SSE reg, create the entry if needed int sse_get_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int forwrite, int sew) { + sse_mark_used(dyn, ninst, a); + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_read |= 1u << a; if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 0) { // it's in the fpu, forget it first... @@ -1800,14 +1848,15 @@ int sse_get_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int forwri dyn->e.ssecache[a].write = forwrite; dyn->e.ssecache[a].vector = 1; dyn->e.ssecache[a].single = 0; // just to be clean + dyn->e.ssecache[a].ymm = 0; + dyn->e.ssecache[a].ymm0 = (dyn->e.ymm0 >> a) & 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[a])); VLE_V(ret, s1, sew, VECTOR_UNMASKED, VECTOR_NFIELD1); return ret; } - -// get rvv register for an SSE reg, but don't try to synch it if it needed to be created int sse_get_reg_empty_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) { + sse_mark_used(dyn, ninst, a); if (dyn->e.ssecache[a].v != -1) { if (dyn->e.ssecache[a].vector == 0) { // it's in the fpu, forget it first... @@ -1831,6 +1880,8 @@ int sse_get_reg_empty_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) dyn->e.ssecache[a].vector = 1; dyn->e.ssecache[a].single = 0; // just to be clean dyn->e.ssecache[a].write = 1; // it will be write... + dyn->e.ssecache[a].ymm = 0; + sse_set_pending_zero(dyn, a, 0); return dyn->e.ssecache[a].reg; } @@ -1841,12 +1892,14 @@ void sse_forget_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a) return; if (dyn->e.ssecache[a].vector == 0) return sse_forget_reg(dyn, ninst, s1, a); - if (dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t == EXT_CACHE_XMMW) { + if (dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t == EXT_CACHE_XMMW + || dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t == EXT_CACHE_YMMW) { uint8_t sew, vlmul, vl; vector_save_vtype(dyn, &sew, &vlmul, &vl); vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); ADDI(s1, xEmu, offsetof(x64emu_t, xmm[a])); VSE8_V(dyn->e.ssecache[a].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, a, dyn->e.ssecache[a].reg, 0, 1); vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); } fpu_free_reg(dyn, dyn->e.ssecache[a].reg); @@ -1872,12 +1925,11 @@ void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1) ++old; } if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 1); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -1898,22 +1950,26 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) int old = -1; uint8_t sew, vlmul, vl; int flushed8 = 0; + uint32_t zeroed = 0; vector_save_vtype(dyn, &sew, &vlmul, &vl); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; for (int i = 0; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (old == -1) { MESSAGE(LOG_DUMP, "\tPurge %sSSE Cache ------\n", next ? "locally " : ""); ++old; } - if (dyn->e.ssecache[i].vector) { + if (next && (dyn->purge_dead_vector & (1u << i))) { + } else if (dyn->e.ssecache[i].vector) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; if (dyn->e.ssecache[i].write) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); } + if (dyn->e.ssecache[i].ymm0) zeroed |= 1u << i; + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next, !next); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -1930,6 +1986,9 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1) if (flushed8) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); + dyn->purge_dead_vector = 0; + if (!next) dyn->e.ymm0 &= ~zeroed; + avx_flush_pending_zero_vector(dyn, ninst, s1, next); if (old != -1) { MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n"); } @@ -1943,12 +2002,11 @@ static void sse_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1) for (int i = 0; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, 0, 0); } else if (dyn->e.ssecache[i].single) FSW(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i])); else @@ -2031,12 +2089,11 @@ void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07) for (int i = start; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VSE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, dyn->e.ssecache[i].ymm0 ? 0 : 1, 1); } } if (flushed8) @@ -2120,14 +2177,27 @@ void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07) for (int i = start; i < 16; ++i) if (dyn->e.ssecache[i].v != -1) { if (dyn->e.ssecache[i].vector) { - if (!flushed8) { - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - flushed8 = 1; - } + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + flushed8 = 1; ADDI(s1, xEmu, offsetof(x64emu_t, xmm[i])); VLE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); } } + if (flushed8 && cpuext.vlen >= 32) { + int nup = 0; + for (int i = start; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector && dyn->e.ssecache[i].ymm && !dyn->e.ssecache[i].ymm0) + ++nup; + if (nup) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + for (int i = start; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector && dyn->e.ssecache[i].ymm && !dyn->e.ssecache[i].ymm0) { + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[i]) - 16); + VLE8_V(dyn->e.ssecache[i].reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + } + } + } if (flushed8) vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); MESSAGE(LOG_DUMP, "\t------- Pop (vector) XMM Cache (%d)\n", n); @@ -2174,11 +2244,8 @@ int fpu_needpurgecache(dynarec_rv64_t* dyn, int ninst) static int findCacheSlot(dynarec_rv64_t* dyn, int ninst, int t, int n, extcache_t* cache) { - ext_cache_t f; - f.n = n; - f.t = t; for (int i = 0; i < 24; ++i) { - if (cache->extcache[i].v == f.v) + if (cache->extcache[i].v && cache->extcache[i].t == t && cache->extcache[i].n == n) return i; if (cache->extcache[i].n == n) { switch (cache->extcache[i].t) { @@ -2208,6 +2275,14 @@ static int findCacheSlot(dynarec_rv64_t* dyn, int ninst, int t, int n, extcache_ if (t == EXT_CACHE_XMMR) return i; break; + case EXT_CACHE_YMMR: + if (t == EXT_CACHE_YMMW) + return i; + break; + case EXT_CACHE_YMMW: + if (t == EXT_CACHE_YMMR) + return i; + break; } } } @@ -2219,7 +2294,9 @@ static void swapCache(dynarec_rv64_t* dyn, int ninst, int s1, int i, int j, extc if (i == j) return; if (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW - || cache->extcache[j].t == EXT_CACHE_XMMR || cache->extcache[j].t == EXT_CACHE_XMMW) { + || cache->extcache[i].t == EXT_CACHE_YMMR || cache->extcache[i].t == EXT_CACHE_YMMW + || cache->extcache[j].t == EXT_CACHE_XMMR || cache->extcache[j].t == EXT_CACHE_XMMW + || cache->extcache[j].t == EXT_CACHE_YMMR || cache->extcache[j].t == EXT_CACHE_YMMW) { SET_CACHE_VECTOR_WIDTH(s1); int reg_i = EXTREG(i); int reg_j = EXTREG(j); @@ -2275,10 +2352,31 @@ static void swapCache(dynarec_rv64_t* dyn, int ninst, int s1, int i, int j, extc cache->extcache[j].v = tmp.v; } +static void loadUpperCache(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int tozero) +{ + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; + if (tozero) { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW32, VECTOR_LMUL1, 2); + VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); + VSLIDEUP_VI(reg, VMASK, 4, VECTOR_UNMASKED); + } else { + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + dyn->inst_vl = 0; // the mask load changed the real vl + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); + VLE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + } + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); +} + static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int s2, int s3, int* s1_val, int* s2_val, int* s3_top, extcache_t* cache, int i, int t, int n) { int reg = EXTREG(i); - if (cache->extcache[i].v && (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW)) { + if (cache->extcache[i].v && (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW || cache->extcache[i].t == EXT_CACHE_YMMR || cache->extcache[i].t == EXT_CACHE_YMMW)) { SET_CACHE_VECTOR_WIDTH(s1); int j = i + 1; while (j < 24 && cache->extcache[j].v) @@ -2321,6 +2419,14 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); VLE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); break; + case EXT_CACHE_YMMR: + case EXT_CACHE_YMMW: + MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n)); + SET_CACHE_VECTOR_WIDTH(s1); + ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); + VLE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); + loadUpperCache(dyn, ninst, s1, n, reg, (cache->ymm0 >> n) & 1); + break; case EXT_CACHE_SS: MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n)); FLW(reg, xEmu, offsetof(x64emu_t, xmm[n])); @@ -2356,12 +2462,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int } *s3_top += a; *s2_val = 0; - if (cpuext.zba) - SH3ADD(s2, s3, xEmu); - else { - SLLI(s2, s3, 3); - ADD(s2, xEmu, s2); - } + ADDSL(s2, xEmu, s3, 3, s2); FLD(reg, s2, offsetof(x64emu_t, x87)); if (t == EXT_CACHE_ST_F) { FCVTSD(reg, reg); @@ -2379,6 +2480,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int } cache->extcache[i].n = n; cache->extcache[i].t = t; + cache->extcache[i].y = (t == EXT_CACHE_YMMR || t == EXT_CACHE_YMMW) ? 1 : 0; } static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int s2, int s3, int* s1_val, int* s2_val, int* s3_top, extcache_t* cache, int i, int t, int n) @@ -2386,18 +2488,21 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i int reg = EXTREG(i); switch (t) { case EXT_CACHE_XMMR: + case EXT_CACHE_YMMR: MESSAGE(LOG_DUMP, "\t - ignoring %s\n", getCacheName(t, n)); break; case EXT_CACHE_XMMW: - MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); - { - uint8_t sew, vlmul, vl; - vector_save_vtype(dyn, &sew, &vlmul, &vl); - vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); - ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); - VSE8_V(reg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - vector_restore_vtype(dyn, ninst, s1, sew, vlmul, vl); + case EXT_CACHE_YMMW: + if (dyn->purge_dead_vector & (1u << n)) { + MESSAGE(LOG_DUMP, "\t - Dropping dead %s\n", getCacheName(t, n)); + break; } + MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); + SET_CACHE_VECTOR_WIDTH(s1); + ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n])); + VSE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); + if (t == EXT_CACHE_YMMW) + avx_flush_upper_vector(dyn, ninst, s1, n, reg, 1, 1); break; case EXT_CACHE_SS: MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n)); @@ -2433,12 +2538,7 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i ANDI(s3, s3, 7); } *s3_top += a; - if (cpuext.zba) - SH3ADD(s2, s3, xEmu); - else { - SLLI(s2, s3, 3); - ADD(s2, xEmu, s2); - } + ADDSL(s2, xEmu, s3, 3, s2); *s2_val = 0; if (t == EXT_CACHE_ST_F) { FCVTDS(reg, reg); @@ -2458,26 +2558,144 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i cache->extcache[i].v = 0; } +static uint16_t vectorDeadAtTarget(dynarec_rv64_t* dyn, int i2, int ninst) +{ + if (i2 <= 0 || i2 >= ninst) + return 0; + for (int i = i2; i < ninst; ++i) { + if (!dyn->insts[i].x64.has_next || dyn->insts[i].x64.has_callret) + return 0; + if (dyn->insts[i].x64.jmp) { + int t = dyn->insts[i].x64.jmp_insts; + if (t > i2 && t <= ninst) + return 0; + } + } + uint16_t live = 0, dead = 0, seen = 0; + for (int i = i2; i <= ninst; ++i) { + uint16_t r = dyn->insts[i].vec_read & (uint16_t)~seen; + live |= r; + seen |= r; + uint16_t w = dyn->insts[i].vec_write_full & (uint16_t)~seen; + dead |= w; + seen |= w; + uint16_t u = (uint16_t)dyn->insts[i].vec_used & (uint16_t)~seen; + live |= u; + seen |= u; + } + return dead; +} + +static void avx_zero_upper(dynarec_rv64_t* dyn, int ninst, int s1, int reg) +{ + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW32, VECTOR_LMUL1, 2); + VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); + VSLIDEUP_VI(reg, VMASK, 4, VECTOR_UNMASKED); + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); +} + +// materialize the deferred zeros of YMM registers that are not in the cache anymore +static void avx_flush_pending_zero_mask(dynarec_rv64_t* dyn, int ninst, int s1, int next, uint16_t mask) +{ + if (!cpuext.vlen || cpuext.vlen < 32) + return; + if (next) { + if (dyn->pending_zero_flushed) + return; + dyn->pending_zero_flushed = 1; + } + for (int i = 0; i < 16; ++i) + if ((mask >> i) & 1) { + SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 0); + SD(xZR, xEmu, offsetof(x64emu_t, ymm[i]) + 8); + if (!next) sse_set_pending_zero(dyn, i, 0); + } + dyn->inst_vl = 0; // force the next vsetvli to be emited +} + +static int find_sse_slot_in(const extcache_t* e, int n, int* is_ymm) +{ + for (int i = 0; i < 24; ++i) { + if (!e->extcache[i].v) + continue; + int t = e->extcache[i].t; + if ((t == EXT_CACHE_XMMR || t == EXT_CACHE_XMMW || t == EXT_CACHE_YMMR || t == EXT_CACHE_YMMW) + && e->extcache[i].n == n) { + if (is_ymm) + *is_ymm = (t == EXT_CACHE_YMMR || t == EXT_CACHE_YMMW); + return i; + } + } + return -1; +} + +static void avx_sync_upper_vector_target(dynarec_rv64_t* dyn, int ninst, int s1, int i2) +{ + if (!cpuext.vlen || cpuext.vlen < 32) + return; + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_used |= 0xffff; + const extcache_t* tgt = &dyn->insts[i2].e; + uint16_t handled = 0; + uint16_t dead = dyn->purge_dead_vector; + for (int i = 0; i < 16; ++i) { + sse_cache_t* c = &dyn->e.ssecache[i]; + if (c->v == -1 || !c->vector) + continue; + if (c->ymm0) + handled |= (uint16_t)(1 << i); + if (dead & (1u << i)) + continue; + int t_ymm = 0; + int t_slot = find_sse_slot_in(tgt, i, &t_ymm); + if (c->ymm && !c->ymm0 && t_slot >= 0 && t_ymm + && !((tgt->ymm0 >> i) & 1) && EXTREG(t_slot) == c->reg) + continue; + avx_flush_upper_vector(dyn, ninst, s1, i, c->reg, 1, 0); + } + avx_flush_pending_zero_mask(dyn, ninst, s1, 1, dyn->e.ymm0 & (uint16_t)~handled & (uint16_t)~dead); +} + static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3) { int i2 = dyn->insts[ninst].x64.jmp_insts; if (i2 < 0) return; + uint16_t dead = vectorDeadAtTarget(dyn, i2, ninst); MESSAGE(LOG_DUMP, "\tCache Transform ---- ninst=%d -> %d\n", ninst, i2); if ((!i2) || (dyn->insts[i2].x64.barrier & BARRIER_FLOAT)) { - if (dyn->e.stack_next) { - fpu_purgecache(dyn, ninst, 1, s1, s2, s3); - MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); - return; - } - for (int i = 0; i < 24; ++i) - if (dyn->e.extcache[i].v) { // there is something at ninst for i + if (!i2) { + int any = 0; + for (int i = 0; i < 24 && !any; ++i) + if (dyn->insts[0].e.extcache[i].v) any = 1; + if (!any && !dyn->e.stack_next) { + dyn->purge_dead_vector = dead; fpu_purgecache(dyn, ninst, 1, s1, s2, s3); MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); return; } - MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); - return; + } else { + if (dyn->e.stack_next) { + dyn->purge_dead_vector = dead; + fpu_purgecache(dyn, ninst, 1, s1, s2, s3); + MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); + return; + } + for (int i = 0; i < 24; ++i) + if (dyn->e.extcache[i].v) { // there is something at ninst for i + dyn->purge_dead_vector = dead; + fpu_purgecache(dyn, ninst, 1, s1, s2, s3); + MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); + return; + } + avx_sync_upper_vector(dyn, ninst, s1, 1); + MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); + return; + } } extcache_t cache_i2 = dyn->insts[i2].e; extcacheUnwind(&cache_i2); @@ -2488,11 +2706,14 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in if (cache_i2.extcache[i].v) purge = 0; if (purge) { + dyn->purge_dead_vector = dead; fpu_purgecache(dyn, ninst, 1, s1, s2, s3); MESSAGE(LOG_DUMP, "\t---- Cache Transform\n"); return; } } + dyn->purge_dead_vector = dead; + avx_sync_upper_vector_target(dyn, ninst, s1, i2); int stack_cnt = dyn->e.stack_next; int s3_top = 0xffff; extcache_t cache = dyn->e; @@ -2510,6 +2731,9 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in j = findCacheSlot(dyn, ninst, EXT_CACHE_XMMW, i, &cache); if (j >= 0 && findCacheSlot(dyn, ninst, EXT_CACHE_XMMW, i, &cache_i2) == -1) unloadCache(dyn, ninst, stack_cnt, s1, s2, s3, &s1_val, &s2_val, &s3_top, &cache, j, cache.extcache[j].t, cache.extcache[j].n); + j = findCacheSlot(dyn, ninst, EXT_CACHE_YMMW, i, &cache); + if (j >= 0 && findCacheSlot(dyn, ninst, EXT_CACHE_YMMW, i, &cache_i2) == -1) + unloadCache(dyn, ninst, stack_cnt, s1, s2, s3, &s1_val, &s2_val, &s3_top, &cache, j, cache.extcache[j].t, cache.extcache[j].n); } for (int i = 0; i < 8; ++i) { int j = findCacheSlot(dyn, ninst, EXT_CACHE_MM, i, &cache); @@ -2568,6 +2792,18 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in cache.extcache[i].t = EXT_CACHE_ST_D; } else if (cache.extcache[i].t == EXT_CACHE_XMMR && cache_i2.extcache[i].t == EXT_CACHE_XMMW) { cache.extcache[i].t = EXT_CACHE_XMMW; + } else if (cache.extcache[i].t == EXT_CACHE_YMMR && cache_i2.extcache[i].t == EXT_CACHE_YMMW) { + cache.extcache[i].t = EXT_CACHE_YMMW; + cache.ssecache[cache.extcache[i].n].write = 1; + } else if (cache.extcache[i].t == EXT_CACHE_YMMW && cache_i2.extcache[i].t == EXT_CACHE_YMMR) { + MESSAGE(LOG_DUMP, "\t - Store %s\n", getCacheName(cache.extcache[i].t, cache.extcache[i].n)); + avx_flush_upper_vector(dyn, ninst, s1, cache.extcache[i].n, EXTREG(i), 1, 0); + SET_CACHE_VECTOR_WIDTH(s1); + ADDI(s1, xEmu, offsetof(x64emu_t, xmm[cache.extcache[i].n])); + VSE_V(EXTREG(i), s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); + cache.extcache[i].t = EXT_CACHE_YMMR; + cache.ssecache[cache.extcache[i].n].write = 0; + cache.ssecache[cache.extcache[i].n].ymm0 = 0; } else if (cache.extcache[i].t == EXT_CACHE_XMMW && cache_i2.extcache[i].t == EXT_CACHE_XMMR) { // refresh cache... MESSAGE(LOG_DUMP, "\t - Refreh %s\n", getCacheName(cache.extcache[i].t, cache.extcache[i].n)); @@ -2577,11 +2813,39 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in cache.extcache[i].t = EXT_CACHE_XMMR; } } + int src_ymm = (cache.extcache[i].t == EXT_CACHE_YMMR || cache.extcache[i].t == EXT_CACHE_YMMW); + int dst_ymm = (cache_i2.extcache[i].t == EXT_CACHE_YMMR || cache_i2.extcache[i].t == EXT_CACHE_YMMW); + if (src_ymm != dst_ymm && cache.extcache[i].n == cache_i2.extcache[i].n) { + int n = cache.extcache[i].n; + if (dst_ymm) { + MESSAGE(LOG_DUMP, "\t - Loading upper half of %s\n", getCacheName(cache.extcache[i].t, n)); + loadUpperCache(dyn, ninst, s1, n, EXTREG(i), (cache_i2.ymm0 >> n) & 1); + } else if (src_ymm) { + MESSAGE(LOG_DUMP, "\t - Storing upper half of %s\n", getCacheName(cache.extcache[i].t, n)); + avx_flush_upper_vector(dyn, ninst, s1, n, EXTREG(i), 1, 0); + } + cache.extcache[i].y = dst_ymm; + } } } - if (stack_cnt != cache_i2.stack) { - MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack); - int a = stack_cnt - cache_i2.stack; + dyn->purge_dead_vector = 0; + uint16_t promote = dyn->insts[i2].promote_ymm; + if (promote) { + for (int r = 0; r < 16; ++r) { + if (!((promote >> r) & 1)) + continue; + const sse_cache_t* src = &dyn->e.ssecache[r]; + const sse_cache_t* dst = &cache_i2.ssecache[r]; + if (dst->v != -1 && dst->vector && dst->ymm + && src->v != -1 && src->vector && !src->ymm && src->ymm0) { + MESSAGE(LOG_DUMP, "\t - Promoting upper half of %s\n", getCacheName(EXT_CACHE_YMMW, r)); + avx_zero_upper(dyn, ninst, s1, dst->reg); + } + } + } + if (stack_cnt != cache_i2.stack || dyn->e.x87stack != cache_i2.x87stack) { + MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d / pending %d -> %d -\n", stack_cnt, cache_i2.stack, dyn->e.x87stack, cache_i2.x87stack); + int a = dyn->e.x87stack - cache_i2.x87stack; // Add x87stack to emu fpu_stack LW(s3, xEmu, offsetof(x64emu_t, fpu_stack)); ADDI(s3, s3, a); @@ -2668,53 +2932,87 @@ static void sewTransform(dynarec_rv64_t* dyn, int ninst, int s1) void CacheTransform(dynarec_rv64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3) { + uint8_t sew = dyn->inst_sew; + uint8_t vlmul = dyn->inst_vlmul; + uint8_t vl = dyn->inst_vl; if (cacheupd & 2) fpuCacheTransform(dyn, ninst, s1, s2, s3); if (cacheupd & 1) flagsCacheTransform(dyn, ninst, s1); if (cacheupd & 4) sewTransform(dyn, ninst, s1); + dyn->inst_sew = sew; + dyn->inst_vlmul = vlmul; + dyn->inst_vl = vl; } -void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val, int zeroup) +void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val) { - // Depending on val, the following insts are emitted. - // val == 0 -> ADDI - // lo12 != 0 && hi20 == 0 -> ADDI - // lo12 == 0 && hi20 != 0 -> LUI - // else -> LUI+ADDI - int32_t hi20 = (val + 0x800) >> 12 & 0xfffff; - int32_t lo12 = val & 0xfff; +#if STEP == 1 + (void)dyn; + (void)ninst; + (void)reg; + (void)val; + return; +#endif +#if STEP == 0 + (void)ninst; + (void)reg; + (void)val; + for (int i = 0; i < RV64_MOV_MAXOPS; ++i) + EMIT(0); + return; +#endif + rv64_mov_seq_t seq; + rv64_mov_dynctx_t ec = { dyn, ninst }; - int src = xZR; - if (hi20) { - LUI(reg, hi20); - src = reg; + if (rv64_mov_cache_get((uint64_t)(uint32_t)val, 0, 1, &seq)) { + rv64_mov_emit_seq(reg, -1, -1, &seq, rv64_mov_emit_word, &ec); + return; } - if (lo12 || !hi20) ADDIW(reg, src, lo12); - if (zeroup && (val & 0x80000000)) { - ZEROUP(reg); + + rv64_movctx_t ctx = { { cpuext.zba, cpuext.zbs, cpuext.zbb }, RV64_MOV_BUDGET }; + if (rv64_mov_seq32(&ctx, (uint32_t)val, 0, &seq)) { + rv64_mov_cache_put((uint64_t)(uint32_t)val, 0, 1, &seq); + rv64_mov_emit_seq(reg, -1, -1, &seq, rv64_mov_emit_word, &ec); } } -void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val) +void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val, int s1, int s2) { - if (((val << 32) >> 32) == val) { - // 32bits value - rv64_move32(dyn, ninst, reg, val, 0); +#if STEP == 1 + (void)dyn; + (void)ninst; + (void)reg; + (void)val; + (void)s1; + (void)s2; + return; +#endif +#if STEP == 0 + (void)ninst; + (void)reg; + (void)val; + (void)s1; + (void)s2; + for (int i = 0; i < RV64_MOV_MAXOPS; ++i) + EMIT(0); + return; +#endif + rv64_mov_seq_t seq; + rv64_mov_dynctx_t ec = { dyn, ninst }; + int nscratch = (s1 >= 0) + (s2 >= 0); + + if (rv64_mov_cache_get((uint64_t)val, nscratch, 0, &seq)) { + rv64_mov_emit_seq(reg, s1, s2, &seq, rv64_mov_emit_word, &ec); return; } - int64_t lo12 = (val << 52) >> 52; - int64_t hi52 = (val + 0x800) >> 12; - int shift = 12 + TrailingZeros64((uint64_t)hi52); - hi52 = ((hi52 >> (shift - 12)) << shift) >> shift; - rv64_move64(dyn, ninst, reg, hi52); - SLLI(reg, reg, shift); - - if (lo12) { - ADDI(reg, reg, lo12); + rv64_movctx_t ctx = { { cpuext.zba, cpuext.zbs, cpuext.zbb }, RV64_MOV_BUDGET }; + if (rv64_mov_seq64(&ctx, (uint64_t)val, 0, nscratch, &seq)) { + rv64_mov_cache_put((uint64_t)val, nscratch, 0, &seq); + rv64_mov_emit_seq(reg, s1, s2, &seq, rv64_mov_emit_word, &ec); } } @@ -2758,15 +3056,13 @@ void emit_pf(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) void fpu_reset_cache(dynarec_rv64_t* dyn, int ninst, int reset_n) { MESSAGE(LOG_DEBUG, "Reset Caches with %d\n", reset_n); -#if STEP > 1 - // for STEP 2 & 3, just need to refresh with current, and undo the changes (push & swap) - dyn->e = dyn->insts[ninst].e; - dyn->vector_sew = dyn->insts[ninst].vector_sew_entry; - extcacheUnwind(&dyn->e); -#else dyn->e = dyn->insts[reset_n].e; dyn->vector_sew = dyn->insts[reset_n].vector_sew_exit; -#endif + dyn->e.ymm0 = dyn->insts[ninst].ymm_pending; + for (int i = 0; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1) + dyn->e.ssecache[i].ymm0 = (dyn->e.ymm0 >> i) & 1; + extcacheUnwind(&dyn->e); #if STEP == 0 if (dyn->need_dump && dyn->need_dump != 3 && dyn->e.x87stack) dynarec_log(LOG_NONE, "New x87stack=%d at ResetCache in inst %d with %d\n", dyn->e.x87stack, ninst, reset_n); #endif @@ -2823,59 +3119,178 @@ void fpu_propagate_stack(dynarec_rv64_t* dyn, int ninst) dyn->e.swapped = 0; } +void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next, int dead) +{ + if (dyn->e.ssecache[a].ymm0) { + // the architectural upper half is zero: write it with scalar stores, no vector state needed + SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 0); + SD(xZR, xEmu, offsetof(x64emu_t, ymm[a]) + 8); + if (!next) dyn->e.ssecache[a].ymm = 0; + return; + } else if (dyn->e.ssecache[a].ymm && dyn->e.ssecache[a].write) { + uint8_t sew0, vlmul0, vl0; + vector_save_vtype(dyn, &sew0, &vlmul0, &vl0); + if (dead || dyn->e.fpu_scratch < 7) { + int sp = dyn->e.fpu_scratch; + int tmp = dead ? reg : fpu_get_scratch(dyn); + int sew = sew0 <= VECTOR_SEW64 ? sew0 : VECTOR_SEW8; + vector_vsetvli(dyn, ninst, s1, sew, VECTOR_LMUL1, 1); + VSLIDEDOWN_VI(tmp, reg, 16 >> sew, VECTOR_UNMASKED); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); + VSE_V(tmp, s1, sew, VECTOR_UNMASKED, VECTOR_NFIELD1); + dyn->e.fpu_scratch = sp; + } else { + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 2); + VECTOR_LOAD_VMASK(0xffff0000, s1, 2); + ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a]) - 16); + VSE8_V(reg, s1, VECTOR_MASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW8, VECTOR_LMUL1, 1); + } + if (!next) dyn->e.ssecache[a].ymm = 0; + vector_restore_vtype(dyn, ninst, s1, sew0, vlmul0, vl0); + } +} + +void avx_promote_upper(dynarec_rv64_t* dyn, int ninst, int s1, uint16_t mask) +{ + for (int r = 0; r < 16; ++r) { + if (!((mask >> r) & 1)) + continue; + sse_cache_t* c = &dyn->e.ssecache[r]; + if (c->v == -1 || !c->vector) { + sse_set_pending_zero(dyn, r, 0); + continue; + } + if (!c->ymm) { + if (c->ymm0) + avx_zero_upper(dyn, ninst, s1, c->reg); + else + loadUpperCache(dyn, ninst, s1, r, c->reg, 0); + c->ymm = 1; + } + c->write = 1; + sse_set_pending_zero(dyn, r, 0); + sse_sync_cache_type(&dyn->e, r); + } +} + +void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) +{ + avx_flush_pending_zero_mask(dyn, ninst, s1, next, dyn->e.ymm0); +} + +void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next) +{ + if (!cpuext.vlen || cpuext.vlen < 32) + return; + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_used |= 0xffff; + #if STEP == 0 + if (!next) dyn->insts[ninst].ymm_pending_materialized = 1; + #endif + uint16_t handled = 0; + for (int i = 0; i < 16; ++i) + if (dyn->e.ssecache[i].v != -1 && dyn->e.ssecache[i].vector) { + if (dyn->e.ssecache[i].ymm0) + handled |= (uint16_t)(1 << i); + avx_flush_upper_vector(dyn, ninst, s1, i, dyn->e.ssecache[i].reg, next, 0); + } + avx_flush_pending_zero_mask(dyn, ninst, s1, next, dyn->e.ymm0 & ~handled); +} + void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int width) { - dyn->vector_sew = sew; + dyn->vector_sew = (width == 16) ? sew : VECTOR_SEWNA; dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, sew, VECTOR_LMUL1, (float)width / 16.0f); } void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); - int low = sse_get_reg_vector(dyn, ninst, s1, a, 0, VECTOR_SEW8); - if (low != vreg) - VMV_V_V(vreg, low); - if (width == 32) { - if (cpuext.vlen == 16) { - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VLE8_V(vreg + 1, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + sse_mark_used(dyn, ninst, a); + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_read |= 1u << a; + if (width == 32 && cpuext.vlen >= 32) + ymm_live_read(dyn, ninst, a); + if (dyn->e.ssecache[a].v != -1 && dyn->e.ssecache[a].vector && (width != 32 || dyn->e.ssecache[a].ymm)) { + int cache = dyn->e.ssecache[a].reg; + avx_set_vector_width(dyn, ninst, s1, sew, width); + if (cache != vreg) VMV_V_V(vreg, cache); + return; + } + int low; + if (width >= 16) { + avx_set_vector_width(dyn, ninst, s1, sew, width); + low = sse_get_reg_vector(dyn, ninst, s1, a, 0, sew); + } else { + avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); + low = sse_get_reg_vector(dyn, ninst, s1, a, 0, VECTOR_SEW8); + } + if (width == 32 && !dyn->e.ssecache[a].ymm) { + if (dyn->e.ssecache[a].ymm0) { + VXOR_VV(VMASK, VMASK, VMASK, VECTOR_UNMASKED); + VSLIDEUP_VI(low, VMASK, 16 >> sew, VECTOR_UNMASKED); } else { - int upper = fpu_get_scratch(dyn); + int sp = dyn->e.fpu_scratch; + int hi = fpu_get_scratch(dyn); + dyn->inst_sew = VECTOR_SEWNA; + dyn->inst_vl = 0; // real vtype here is unknown, never elide vsetvli + int sew0 = sew <= VECTOR_SEW64 ? sew : VECTOR_SEW8; + vector_vsetvli(dyn, ninst, s1, sew0, VECTOR_LMUL1, 1); ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VLE8_V(upper, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 32); - VSLIDEUP_VI(vreg, upper, 16, VECTOR_UNMASKED); + VLE_V(hi, s1, sew0, VECTOR_UNMASKED, VECTOR_NFIELD1); + vector_vsetvli(dyn, ninst, s1, sew0, VECTOR_LMUL1, 2); + VSLIDEUP_VI(low, hi, 16 >> sew0, VECTOR_UNMASKED); + dyn->e.fpu_scratch = sp; } + dyn->e.ssecache[a].ymm = 1; + sse_set_pending_zero(dyn, a, 0); } + if (low != vreg) + VMV_V_V(vreg, low); avx_set_vector_width(dyn, ninst, s1, sew, width); } void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew) { - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); - sse_forget_reg_vector(dyn, ninst, s1, a); - ADDI(s1, xEmu, offsetof(x64emu_t, xmm[a])); - VSE8_V(vreg, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); - if (width == 32) { - if (cpuext.vlen == 16) { - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VSE8_V(vreg + 1, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + sse_mark_used(dyn, ninst, a); + if (ninst >= 0 && ninst < dyn->size) + dyn->insts[ninst].vec_write_full |= 1u << a; + int cache = sse_get_reg_empty_vector(dyn, ninst, s1, a); + if (cache != vreg) { + avx_set_vector_width(dyn, ninst, s1, sew, width); + VMV_V_V(cache, vreg); + } + if (cpuext.vlen >= 32) { + dyn->e.ssecache[a].ymm = (width == 32); + dyn->e.extcache[EXTIDX(cache)].y = (width == 32); + if (width == 16) { + sse_set_pending_zero(dyn, a, 1); + ymm_live_zero(dyn, ninst, a); } else { - int upper = (vreg == 1) ? 2 : 1; - // v1/v2 are also the fixed cache slots of MMX6/MMX7, so flush any live MMX cache there before using it as scratch - mmx_flush_reg_preserve_vtype(dyn, ninst, s1, upper == 1 ? 6 : 7); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 32); - VSLIDEDOWN_VI(upper, vreg, 16, VECTOR_UNMASKED); - avx_set_vector_width(dyn, ninst, s1, VECTOR_SEW8, 16); - ADDI(s1, xEmu, offsetof(x64emu_t, ymm[a])); - VSE8_V(upper, s1, VECTOR_UNMASKED, VECTOR_NFIELD1); + sse_set_pending_zero(dyn, a, 0); + ymm_live_write(dyn, ninst, a); } - } else { - YMM0(a); } avx_set_vector_width(dyn, ninst, s1, sew, width); } +void doPreload(dynarec_rv64_t* dyn, int ninst) +{ + uint32_t preload = dyn->insts[ninst].preload_xmmymm; + if (!preload) + return; + uint16_t saved_read = dyn->insts[ninst].vec_read; + MESSAGE(LOG_INFO, "Preload XMM/YMM -------- %x\n", preload); + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16); + for (int i = 0; i < 16; ++i) + if (preload & (1u << i)) + sse_get_reg_vector(dyn, ninst, x1, i, 0, VECTOR_SEW8); + dyn->insts[ninst].vec_read = saved_read; + MESSAGE(LOG_INFO, "-------- Preload XMM/YMM\n"); +} + // Simple wrapper for vsetvli, may use s1 as scratch int vector_vsetvli(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int vlmul, float multiple) { @@ -3145,52 +3560,23 @@ void vector_loadmask(dynarec_rv64_t* dyn, int ninst, int vreg, uint64_t imm, int } else abort(); } else { - int sew = dyn->vector_eew; - int count; - int scratch; - int result; - int first; - int scratch_mark = dyn->e.fpu_scratch; - if (sew < VECTOR_SEW8 || sew > VECTOR_SEW64) + uint8_t sv_sew, sv_vlmul, sv_vl; + if (sew > VECTOR_SEW64) sew = VECTOR_SEW8; - count = (16 >> sew) * (int)multiple; + int count = (int)((16 >> sew) * multiple); if (count > 32) count = 32; - scratch = fpu_get_scratch(dyn); - result = fpu_get_scratch(dyn); - uint8_t cur_sew = dyn->inst_sew; - uint8_t cur_vlmul = dyn->inst_vlmul; - float cur_multiple = (cur_sew == VECTOR_SEWNA || (16 >> cur_sew) == 0) ? 1.0 : (float)dyn->inst_vl / (float)(16 >> cur_sew); - int need_wrap = (cur_sew != VECTOR_SEWNA && cur_vlmul != VECTOR_LMUL1); - if (need_wrap) vector_vsetvli(dyn, ninst, s1, cur_sew, VECTOR_LMUL1, cur_multiple); - first = 1; - VID_V(scratch, VECTOR_UNMASKED); - for (int i = 0; i < count; ++i) { - if (imm & (1ULL << i)) { - if (first) { - if (i < 16) { - VMSEQ_VI(vreg, scratch, i, VECTOR_UNMASKED); - } else { - ADDI(s1, xZR, i); - VMSEQ_VX(vreg, scratch, s1, VECTOR_UNMASKED); - } - first = 0; - } else { - if (i < 16) { - VMSEQ_VI(result, scratch, i, VECTOR_UNMASKED); - } else { - ADDI(s1, xZR, i); - VMSEQ_VX(result, scratch, s1, VECTOR_UNMASKED); - } - VMOR_MM(vreg, vreg, result); - } - } - } - if (first) - VMSNE_VV(vreg, scratch, scratch, VECTOR_UNMASKED); + imm &= (1ULL << count) - 1; + vector_save_vtype(dyn, &sv_sew, &sv_vlmul, &sv_vl); + int need_wrap = (sv_sew > VECTOR_SEW64 || sv_vlmul != VECTOR_LMUL1 || !sv_vl); + if ((sv_sew == VECTOR_SEW8 && count > 8) || (sv_sew == VECTOR_SEW16 && count > 16)) + need_wrap |= 1; + if (need_wrap) + vector_vsetvli(dyn, ninst, s1, VECTOR_SEW64, VECTOR_LMUL1, 1); + MOV64x(s1, imm); + VMV_S_X(vreg, s1); if (need_wrap) - vector_vsetvli(dyn, ninst, s1, cur_sew, cur_vlmul, cur_multiple); - dyn->e.fpu_scratch = scratch_mark; + vector_restore_vtype(dyn, ninst, s1, sv_sew, sv_vlmul, sv_vl); } #endif } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 23d93c1de..b219719de 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -20,6 +20,10 @@ #include "../emu/x64primop.h" #include "dynarec_rv64_consts.h" +#ifndef ENDPREFIX +#define ENDPREFIX +#endif + #define F8 *(uint8_t*)(addr++) #define F8S *(int8_t*)(addr++) #define F16 *(uint16_t*)(addr += 2, addr - 2) @@ -37,13 +41,130 @@ // LOCK_* define #define LOCK_LOCK (int*)1 +#if STEP == 0 +#define UP32_READ(r) \ + do { \ + if (IS_GPR(r)) dyn->insts[ninst].up32_read |= (uint16_t)(1 << (TO_X64(r))); \ + } while (0) +#define UP32_WRITE64(r) \ + do { \ + if (IS_GPR(r)) dyn->insts[ninst].up32_write64 |= (uint16_t)(1 << (TO_X64(r))); \ + } while (0) +#define UP32_WRITE32(r) \ + do { \ + if (IS_GPR(r)) { \ + UP32_WRITE64(r); \ + dyn->insts[ninst].up32_write32 |= (uint16_t)(1 << (TO_X64(r))); \ + } \ + } while (0) +#define UP32_READALL() \ + do { \ + dyn->insts[ninst].up32_read |= (uint16_t)0xFFFF; \ + } while (0) +#else +#define UP32_READ(r) ((void)(r)) +#define UP32_WRITE64(r) ((void)(r)) +#define UP32_WRITE32(r) ((void)(r)) +#define UP32_READALL() ((void)0) +#endif + +#if STEP == 1 +#define UP32_ZERO(r) \ + do { \ + if (IS_GPR(r)) dyn->insts[ninst].up32_zero |= (uint16_t)(1 << (TO_X64(r))); \ + } while (0) +#else +#define UP32_ZERO(r) ((void)(r)) +#endif + +#define ZEROUP_RESULT(r) \ + do { \ + ZEROUP(r); \ + UP32_ZERO(r); \ + } while (0) + +#define MARKREGd(r) \ + do { \ + if (rex.w) \ + UP32_WRITE64(r); \ + else \ + UP32_WRITE32(r); \ + } while (0) + +#define MARKREGdz(r) \ + do { \ + if (!rex.is32bits) \ + UP32_WRITE64(r); \ + else \ + UP32_WRITE32(r); \ + } while (0) + +#define MARKREGs(r) \ + do { \ + if (rex.w) UP32_READ(r); \ + } while (0) + +#define MARKREGsz(r) \ + do { \ + if (!rex.is32bits) UP32_READ(r); \ + } while (0) + +#define MARKREGsd(r) \ + do { \ + MARKREGs(r); \ + MARKREGd(r); \ + } while (0) + +#define MARKREGsdz(r) \ + do { \ + MARKREGsz(r); \ + MARKREGdz(r); \ + } while (0) + +#define NEED_ZEROUP32(r) \ + (!(IS_GPR(r)) || !((dyn->insts[ninst].up32_skip >> (TO_X64(r))) & 1)) +#define NEED_ZEROUP(r) (!rex.w && NEED_ZEROUP32(r)) + +#define ZEROUP32_RESULT(r) \ + do { \ + UP32_WRITE32(r); \ + if (NEED_ZEROUP32(r)) ZEROUP_RESULT(r); \ + } while (0) + // GETGD get x64 register in gd -#define GETGD gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)) -#define GETVD vd = TO_NAT(vex.v) +#define GETGDw gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)) +#define GETGDs \ + do { \ + GETGDw; \ + MARKREGs(gd); \ + } while (0) +#define GETGD GETGDs +#define GETGDd \ + do { \ + GETGDw; \ + MARKREGd(gd); \ + } while (0) +#define GETGDsd \ + do { \ + GETGDs; \ + MARKREGd(gd); \ + } while (0) +#define GETVDs \ + do { \ + vd = TO_NAT(vex.v); \ + MARKREGs(vd); \ + } while (0) +#define GETVDsd \ + do { \ + vd = TO_NAT(vex.v); \ + MARKREGsd(vd); \ + } while (0) +#define GETVD GETVDs // GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI #define GETED(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -51,10 +172,16 @@ LDxw(x1, wback, fixedaddress); \ ed = x1; \ } +#define GETEDsd(D) \ + do { \ + GETED(D); \ + if (MODREG) MARKREGd(ed); \ + } while (0) // GETSED can use r1 for ed, and r2 for wback. ed will be sign extended! #define GETSED(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ if (!rex.w) { \ ADDW(x1, ed, xZR); \ @@ -73,6 +200,7 @@ #define GETEDx(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + UP32_READ(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -83,6 +211,7 @@ #define GETEDz(D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -94,6 +223,7 @@ #define GETEDH(hint, ret, D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ wback = 0; \ } else { \ SMREAD(); \ @@ -105,6 +235,7 @@ #define GETEDW(hint, ret, D) \ if (MODREG) { \ ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ + MARKREGs(ed); \ MV(ret, ed); \ wback = 0; \ } else { \ @@ -399,9 +530,15 @@ gback = xEmu; \ gdoffset = offsetof(x64emu_t, xmm[gd]) -#define GETGY() \ - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ - /* TODO: forget */ \ +#define GETGY() \ + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ + if (dyn->e.ssecache[gd].v != -1 && dyn->e.ssecache[gd].vector) \ + avx_flush_upper_vector(dyn, ninst, x3, gd, dyn->e.ssecache[gd].reg, 0, 0); \ + if (dyn->e.ymm0 & (1 << gd)) { \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 0); \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 8); \ + sse_set_pending_zero(dyn, gd, 0); \ + } \ gyoffset = offsetof(x64emu_t, ymm[gd]) #define GETVX() \ @@ -409,8 +546,14 @@ vback = xEmu; \ vxoffset = offsetof(x64emu_t, xmm[vex.v]) -#define GETVY() \ - /* TODO: forget */ \ +#define GETVY() \ + if (dyn->e.ssecache[vex.v].v != -1 && dyn->e.ssecache[vex.v].vector) \ + avx_flush_upper_vector(dyn, ninst, x3, vex.v, dyn->e.ssecache[vex.v].reg, 0, 0); \ + if (dyn->e.ymm0 & (1 << vex.v)) { \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[vex.v]) + 0); \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[vex.v]) + 8); \ + sse_set_pending_zero(dyn, vex.v, 0); \ + } \ vyoffset = offsetof(x64emu_t, ymm[vex.v]); // Get Ex address in general register a, will purge SS or SD if it's reg and is loaded. May use x3. Use wback as load address! @@ -427,14 +570,20 @@ } -#define GETEY() \ - if (MODREG) { \ - ed = (nextop & 7) + (rex.b << 3); \ - /* TODO: forget */ \ - wback = xEmu; \ - fixedaddress = offsetof(x64emu_t, ymm[ed]); \ - } else { \ - fixedaddress += 16; \ +#define GETEY() \ + if (MODREG) { \ + ed = (nextop & 7) + (rex.b << 3); \ + if (dyn->e.ssecache[ed].v != -1 && dyn->e.ssecache[ed].vector) \ + avx_flush_upper_vector(dyn, ninst, x3, ed, dyn->e.ssecache[ed].reg, 0, 0); \ + if (dyn->e.ymm0 & (1 << ed)) { \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[ed]) + 0); \ + SD(xZR, xEmu, offsetof(x64emu_t, ymm[ed]) + 8); \ + sse_set_pending_zero(dyn, ed, 0); \ + } \ + wback = xEmu; \ + fixedaddress = offsetof(x64emu_t, ymm[ed]); \ + } else { \ + fixedaddress += 16; \ } @@ -471,30 +620,31 @@ #define GETVY_vector(a, sew) \ do { \ - a = fpu_get_scratch(dyn); \ + a = VREG(vex.v); \ avx_load_reg_vector(dyn, ninst, x1, a, vex.v, 16 << vex.l, sew); \ } while (0) #define GETGY_vector(a, sew) \ do { \ gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ - a = fpu_get_scratch(dyn); \ + a = VREG(gd); \ avx_load_reg_vector(dyn, ninst, x1, a, gd, 16 << vex.l, sew); \ } while (0) -#define GETGY_empty_vector(a) \ - do { \ - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ - a = fpu_get_scratch(dyn); \ +#define GETGY_empty_vector(a) \ + do { \ + gd = ((nextop & 0x38) >> 3) + (rex.r << 3); \ + a = sse_get_reg_empty_vector(dyn, ninst, x1, gd); \ } while (0) #define GETEY_vector(a, D, sew) \ do { \ - a = fpu_get_scratch(dyn); \ if (MODREG) { \ + a = VREG((nextop & 7) + (rex.b << 3)); \ avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), \ 16 << vex.l, sew); \ } else { \ + a = fpu_get_scratch(dyn); \ SMREAD(); \ addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, D); \ SET_AVX_VECTOR_WIDTH(x1, sew); \ @@ -505,10 +655,11 @@ // Get EY as a 128bits vector, even if vex.l is set #define GETEY128_vector(a, D, sew) \ do { \ - a = fpu_get_scratch(dyn); \ if (MODREG) { \ - avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), 16, sew); \ + a = VREG((nextop & 7) + (rex.b << 3)); \ + avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), 16, sew); \ } else { \ + a = fpu_get_scratch(dyn); \ SMREAD(); \ addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, D); \ avx_set_vector_width(dyn, ninst, x1, sew, 16); \ @@ -517,13 +668,52 @@ SET_AVX_VECTOR_WIDTH(x1, sew); \ } while (0) +#define VEC_SRC_KEEP(a, dst) \ + do { \ + if ((a) == (dst)) { \ + int keep_ = fpu_get_scratch(dyn); \ + VMV_V_V(keep_, (a)); \ + (a) = keep_; \ + } \ + } while (0) + +#define GETGY_empty_VYEY_vector_D(gx, vx, ex, sew, D) \ + do { \ + GETVY_vector(vx, sew); \ + GETEY_vector(ex, D, sew); \ + GETGY_empty_vector(gx); \ + } while (0) + +#define GETGY_empty_VYEY_vector(gx, vx, ex, sew) \ + GETGY_empty_VYEY_vector_D(gx, vx, ex, sew, 0) + +#define GETGY_empty_VYEY_vector_safe(gx, vx, ex, sew) \ + do { \ + GETVY_vector(vx, sew); \ + GETEY_vector(ex, 0, sew); \ + GETGY_empty_vector(gx); \ + VEC_SRC_KEEP(vx, gx); \ + VEC_SRC_KEEP(ex, gx); \ + } while (0) + +#define VEC_SRC_SAFE(a, dst) \ + do { \ + if ((a) == (dst)) { \ + int safe_ = fpu_get_scratch(dyn); \ + avx_set_vector_width(dyn, ninst, x1, VECTOR_SEW8, 16 << vex.l); \ + VMV_V_V(safe_, (a)); \ + (a) = safe_; \ + } \ + } while (0) + // Get EY as a vector of w bytes (for instructions whose source operand is narrower than the destination) #define GETEY_vector_w(a, D, sew, w) \ do { \ - a = fpu_get_scratch(dyn); \ if (MODREG) { \ + a = VREG((nextop & 7) + (rex.b << 3)); \ avx_load_reg_vector(dyn, ninst, x1, a, (nextop & 7) + (rex.b << 3), w, sew); \ } else { \ + a = fpu_get_scratch(dyn); \ SMREAD(); \ addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, D); \ avx_set_vector_width(dyn, ninst, x1, sew, w); \ @@ -551,6 +741,60 @@ #define GETEX32_vector(a, w, D, sew) GETEX_PARTIAL_vector(a, w, D, sew, 0.25) #define GETEX16_vector(a, w, D, sew) GETEX_PARTIAL_vector(a, w, D, sew, 0.125) +#define VRGATHER_VX_SAFE(vd, vs2, rs1, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VRGATHER_VX(d_, s_, (rs1), (vm)); \ + } while (0) + +#define VRGATHER_VV_SAFE(vd, vs2, vs1, vm) \ + do { \ + int d_ = (vd), s2_ = (vs2), s1_ = (vs1); \ + if (d_ == s2_) { \ + s2_ = fpu_get_scratch(dyn); \ + VMV_V_V(s2_, (vs2)); \ + } \ + if (d_ == s1_) { \ + s1_ = fpu_get_scratch(dyn); \ + VMV_V_V(s1_, (vs1)); \ + } \ + VRGATHER_VV(d_, s2_, s1_, (vm)); \ + } while (0) + +#define VSLIDEUP_VI_SAFE(vd, vs2, imm, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VSLIDEUP_VI(d_, s_, (imm), (vm)); \ + } while (0) + +#define VSLIDEUP_VX_SAFE(vd, vs2, rs1, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VSLIDEUP_VX(d_, s_, (rs1), (vm)); \ + } while (0) + +#define VSLIDE1UP_VX_SAFE(vd, vs2, rs1, vm) \ + do { \ + int d_ = (vd), s_ = (vs2); \ + if (d_ == s_) { \ + s_ = fpu_get_scratch(dyn); \ + VMV_V_V(s_, (vs2)); \ + } \ + VSLIDE1UP_VX(d_, s_, (rs1), (vm)); \ + } while (0) + // Put Back EX if it was a memory and not an emm register #define PUTEX_vector(a, sew) \ if (!MODREG) { \ @@ -757,6 +1001,8 @@ #define GETMARK2 GETMARKi(1) #define MARK3 MARKi(2) #define GETMARK3 GETMARKi(2) +#define MARK4 MARKi(3) +#define GETMARK4 GETMARKi(3) #define MARKFi(i) dyn->insts[ninst].markf[i] = dyn->native_size #define GETMARKFi(i) dyn->insts[ninst].markf[i] @@ -765,6 +1011,9 @@ #define MARKF2 MARKFi(1) #define GETMARKF2 GETMARKFi(1) +#define MARKFNAN dyn->insts[ninst].markfnan = dyn->native_size +#define GETMARKFNAN dyn->insts[ninst].markfnan + #define MARKSEG dyn->insts[ninst].markseg = dyn->native_size #define GETMARKSEG dyn->insts[ninst].markseg #define MARKLOCK dyn->insts[ninst].marklock = dyn->native_size @@ -829,6 +1078,12 @@ #define BEQZ_MARK2(reg) BEQ_MARK2(reg, xZR) // Branch to MARK3 if reg1==0 (use j64) #define BEQZ_MARK3(reg) BEQ_MARK3(reg, xZR) +// Branch to MARK4 if reg1!=reg2 (use j64) +#define BNE_MARK4(reg1, reg2) Bxx_gen(NE, MARK4, reg1, reg2) +// Branch to MARK4 if reg1!=0 (use j64) +#define BNEZ_MARK4(reg) BNE_MARK4(reg, xZR) +// Branch to MARK4 instruction unconditionnal (use j64) +#define B_MARK4_nocond Bxx_gen(__, MARK4, 0, 0) // Branch to MARK3 instruction unconditionnal (use j64) #define B_MARK3_nocond Bxx_gen(__, MARK3, 0, 0) // Branch to MARKLOCK if reg1!=reg2 (use j64) @@ -920,7 +1175,7 @@ BNE_MARK2(xs, xZR); \ FEQS(xt, vb, vb); \ FMVS(v1, va); \ - Bxx_gen(NE, MARKF, xt, xZR); \ + Bxx_gen(NE, MARKFNAN, xt, xZR); \ FMVXW(xs, va); \ SLLIW(xs, xs, 9); \ SRLIW(xs, xs, 9); \ @@ -931,25 +1186,25 @@ BEQ_MARKLOCK(xs, xt); \ Bxx_gen(LTU, MARKLOCK2, xs, xt); \ FMVS(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK2; \ FMVS(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK; \ FMVXW(xs, va); \ SRLIW(xs, xs, 31); \ BNEZ_MARKLOCK2(xs); \ FMVS(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK2; \ FEQS(xt, vb, vb); \ BNE_MARK3(xt, xZR); \ FMVS(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK3; \ FNEGS(v1, v1); \ Bxx_gen(__, MARK, 0, 0); \ - MARKF; \ + MARKFNAN; \ FMVXW(xs, v1); \ BSETI(xs, xs, 22, xq); \ FMVWX(v1, xs); \ @@ -964,7 +1219,7 @@ BNE_MARK2(xs, xZR); \ FEQD(xt, vb, vb); \ FMVD(v1, va); \ - Bxx_gen(NE, MARKF, xt, xZR); \ + Bxx_gen(NE, MARKFNAN, xt, xZR); \ FMVXD(xs, va); \ SLLI(xs, xs, 12); \ BSETI(xs, xs, 63, xq); \ @@ -973,25 +1228,25 @@ BEQ_MARKLOCK(xs, xt); \ Bxx_gen(LTU, MARKLOCK2, xs, xt); \ FMVD(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK2; \ FMVD(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARKLOCK; \ FMVXD(xs, va); \ SRLI(xs, xs, 63); \ BNEZ_MARKLOCK2(xs); \ FMVD(v1, va); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK2; \ FEQD(xt, vb, vb); \ BNE_MARK3(xt, xZR); \ FMVD(v1, vb); \ - Bxx_gen(__, MARKF, 0, 0); \ + Bxx_gen(__, MARKFNAN, 0, 0); \ MARK3; \ FNEGD(v1, v1); \ Bxx_gen(__, MARK, 0, 0); \ - MARKF; \ + MARKFNAN; \ FMVXD(xs, v1); \ BSETI(xs, xs, 51, xq); \ FMVDX(v1, xs); \ @@ -1016,6 +1271,20 @@ MARKSEG #endif +#ifndef X87_DOUBLE_TO_FLOAT +#define X87_DOUBLE_TO_FLOAT(d, sd, xs, xt) \ + FMVXD(xs, sd); \ + SRLI(xt, xs, 63); \ + SLLI(xt, xt, 31); \ + SRLI(xs, xs, 29); \ + SLLI(xs, xs, 41); \ + SRLI(xs, xs, 41); \ + OR(xs, xs, xt); \ + MOV32w(xt, 0x7FC00000); \ + OR(xs, xs, xt); \ + FMVWX(d, xs) +#endif + #define STORE_REG(A) SD(x##A, xEmu, offsetof(x64emu_t, regs[_##A])) #define LOAD_REG(A) LD(x##A, xEmu, offsetof(x64emu_t, regs[_##A])) @@ -1161,8 +1430,7 @@ // Adjust the xFlags bit 5 -> bit 11, src and dst can be the same (and can be xFlags, but not s1) #define FLAGS_ADJUST_TO11(dst, src, s1) \ - LUI(s1, 0xFFFFF); \ - ADDIW(s1, s1, 0x7DF); \ + MOV64x(s1, 0xFFFFFFFFFFFFF7DF); \ AND(s1, src, s1); \ ANDI(dst, src, 1 << 5); \ SLLI(dst, dst, 11 - 5); \ @@ -1238,18 +1506,36 @@ READFLAGS(A) #endif -#define NAT_FLAGS_OPS(op1, op2, s1, s2) \ - do { \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = op1; \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = op2; \ - if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op1)) { \ - MV(s1, op1); \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = s1; \ - } \ - if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op2)) { \ - MV(s2, op2); \ - dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = s2; \ - } \ +#define NAT_FLAGS_OPS(op1, op2, s1, s2) \ + do { \ + int nat_op1 = op1; \ + int nat_op2 = op2; \ + int nat_next = dyn->insts[ninst].nat_next_inst; \ + int nat_last = nat_next; \ + while (nat_last && dyn->insts[nat_last].nat_next_inst) \ + nat_last = dyn->insts[nat_last].nat_next_inst; \ + int nat_copy = 0; \ + for (int nat_i = ninst + 1; nat_i < nat_last; ++nat_i) \ + if (dyn->insts[nat_i].no_scratch_usage) \ + nat_copy = 1; \ + if (nat_copy && IS_GPR(nat_op1)) { \ + if (dyn->insts[ninst].up32_read & (1 << TO_X64(nat_op1))) \ + MV(s1, nat_op1); \ + else \ + ZEXTW2(s1, nat_op1); \ + nat_op1 = s1; \ + } \ + if (nat_copy && IS_GPR(nat_op2)) { \ + if (dyn->insts[ninst].up32_read & (1 << TO_X64(nat_op2))) \ + MV(s2, nat_op2); \ + else \ + ZEXTW2(s2, nat_op2); \ + nat_op2 = s2; \ + } \ + for (int nat_i = nat_next; nat_i; nat_i = dyn->insts[nat_i].nat_next_inst) { \ + dyn->insts[nat_i].nat_flags_op1 = nat_op1; \ + dyn->insts[nat_i].nat_flags_op2 = nat_op2; \ + } \ } while (0) #define NAT_FLAGS_ENABLE_CARRY() dyn->insts[ninst].nat_flags_carry = 1 @@ -1332,16 +1618,29 @@ #define TABLE64_(A, V) #endif -#define ARCH_INIT() \ - SMSTART(); \ - dyn->vector_sew = VECTOR_SEWNA; - -#define ARCH_RESET() \ - dyn->vector_sew = VECTOR_SEWNA; +#define ARCH_INIT() \ + SMSTART(); \ + dyn->vector_sew = VECTOR_SEWNA; \ + dyn->inst_sew = VECTOR_SEWNA; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; \ + dyn->e.ymm0 = 0; + +#define ARCH_RESET() \ + dyn->vector_sew = VECTOR_SEWNA; \ + dyn->inst_sew = VECTOR_SEWNA; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; + +#undef PREFLAGSNEEDED +#define PREFLAGSNEEDED() \ + if (dyn->always_test && ninst && dyn->insts[ninst - 1].x64.has_callret) \ + checkCRC(dyn, ninst); #if STEP < 2 #define GETIP(A, scratch) #define GETIP_(A, scratch) +#define GETRETADDR(A, reg, scratch) #else #define GETIP_(A, scratch) \ do { \ @@ -1373,6 +1672,21 @@ GETIP_(A, scratch); \ dyn->last_ip = (A); +#define GETRETADDR(A, reg, scratch) \ + do { \ + ssize_t _delta_ra = (ssize_t)(A) - (ssize_t)dyn->last_ip; \ + if (dyn->last_ip && _delta_ra >= -2048 && _delta_ra < 2048) { \ + if (_delta_ra) \ + ADDI(reg, xRIP, _delta_ra); \ + else \ + MV(reg, xRIP); \ + } else if (dyn->need_reloc) { \ + TABLE64(reg, (A)); \ + } else { \ + MOV64x(reg, (A)); \ + } \ + } while (0) + #endif #define CLEARIP() dyn->last_ip = 0 @@ -1389,19 +1703,132 @@ #define MODREG ((nextop & 0xC0) == 0xC0) #ifndef SET_ELEMENT_WIDTH -#define SET_ELEMENT_WIDTH(s1, sew, set) \ - do { \ - if ((sew) == VECTOR_SEWANY && dyn->vector_sew != VECTOR_SEWNA) { \ - dyn->vector_eew = dyn->vector_sew; \ - } else if ((sew) == dyn->vector_sew) { \ - dyn->vector_eew = dyn->vector_sew; \ - } else { \ - dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, (sew), VECTOR_LMUL1, 1); \ - } \ - if (set) dyn->vector_sew = dyn->vector_eew; \ +#define SET_ELEMENT_WIDTH(s1, sew, set) \ + do { \ + if ((sew) == VECTOR_SEWANY && (unsigned)dyn->vector_sew < 4 \ + && dyn->inst_vl == (uint32_t)(16u >> dyn->vector_sew)) { \ + dyn->vector_eew = dyn->vector_sew; \ + } else if ((sew) == dyn->vector_sew && (unsigned)(sew) < 4 && dyn->inst_vl == (uint32_t)(16u >> (sew))) { \ + dyn->vector_eew = dyn->vector_sew; \ + } else { \ + dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, (sew), VECTOR_LMUL1, 1); \ + } \ + if (set) dyn->vector_sew = dyn->vector_eew; \ } while (0) #endif +#define SET_SCALAR_FP_WIDTH(s1, sew) \ + do { \ + dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, (sew), VECTOR_LMUL1, \ + 1.0f / (float)(16 >> (sew))); \ + dyn->vector_sew = dyn->vector_eew; \ + } while (0) + +#define AVX_SCALAR_OP_PROLOG_D(SEW, D) \ + do { \ + q0 = VREG(vex.v); \ + avx_load_reg_vector(dyn, ninst, x1, q0, vex.v, 16, (SEW)); \ + if (MODREG) { \ + ed = (nextop & 7) + (rex.b << 3); \ + q1 = VREG(ed); \ + avx_load_reg_vector(dyn, ninst, x1, q1, ed, 16, (SEW)); \ + } else { \ + q1 = -1; \ + } \ + GETGY_empty_vector(v0); \ + if (v0 != q0) { \ + if (v0 == q1) { \ + int _t = fpu_get_scratch(dyn); \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ + VMV_V_V(_t, q1); \ + q1 = _t; \ + } \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 16); \ + VMV_V_V(v0, q0); \ + } \ + if (!MODREG) { \ + q1 = fpu_get_scratch(dyn); \ + SMREAD(); \ + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, (D)); \ + avx_set_vector_width(dyn, ninst, x1, (SEW), 1 << (SEW)); \ + VLE_V(q1, ed, (SEW), VECTOR_UNMASKED, VECTOR_NFIELD1); \ + } \ + SET_SCALAR_FP_WIDTH(x1, (SEW)); \ + } while (0) + +#define AVX_SCALAR_OP_PROLOG(SEW) AVX_SCALAR_OP_PROLOG_D(SEW, 0) + +#define AVX_SCALAR_OP_STORE(SEW) \ + avx_store_reg_vector(dyn, ninst, x1, v0, gd, 16, (SEW)) + +#define AVX_CMP_ORDERED_MASK() \ + do { \ + VMFEQ_VV(q2, q0, q0, VECTOR_UNMASKED); \ + VMFEQ_VV(d0, q1, q1, VECTOR_UNMASKED); \ + VMAND_MM(q2, q2, d0); \ + } while (0) + +#define AVX_SCALAR_CMP(SEW) \ + do { \ + AVX_SCALAR_OP_PROLOG_D(SEW, 1); \ + u8 = F8; \ + q2 = fpu_get_scratch(dyn); \ + d0 = fpu_get_scratch(dyn); \ + switch (u8 & 0xf) { \ + case 0x0: VMFEQ_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; \ + case 0x1: VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; \ + case 0x2: VMFLE_VV(VMASK, q0, q1, VECTOR_UNMASKED); break; \ + case 0x3: \ + AVX_CMP_ORDERED_MASK(); \ + VMNAND_MM(VMASK, q2, q2); \ + break; \ + case 0x4: \ + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0x5: \ + VMFLT_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0x6: \ + VMFLE_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0x7: \ + AVX_CMP_ORDERED_MASK(); \ + VMAND_MM(VMASK, q2, q2); \ + break; \ + case 0x8: \ + AVX_CMP_ORDERED_MASK(); \ + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, q2, q2); \ + VMOR_MM(VMASK, VMASK, d0); \ + break; \ + case 0x9: \ + VMFLE_VV(d0, q1, q0, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0xa: \ + VMFLT_VV(d0, q1, q0, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + break; \ + case 0xb: VMXOR_MM(VMASK, q2, q2); break; \ + case 0xc: \ + AVX_CMP_ORDERED_MASK(); \ + VMFEQ_VV(d0, q0, q1, VECTOR_UNMASKED); \ + VMNAND_MM(VMASK, d0, d0); \ + VMAND_MM(VMASK, VMASK, q2); \ + break; \ + case 0xd: VMFLE_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; \ + case 0xe: VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED); break; \ + case 0xf: VMXNOR_MM(VMASK, q2, q2); break; \ + } \ + VXOR_VV(q2, q2, q2, VECTOR_UNMASKED); \ + VMERGE_VIM(q2, q2, 0x1f); \ + VMV_V_V(v0, q2); \ + AVX_SCALAR_OP_STORE(SEW); \ + } while (0) + #define SET_CACHE_VECTOR_WIDTH(S1) \ do { \ int sew = dyn->vector_sew; \ @@ -1471,6 +1898,7 @@ #define jump_to_epilog_fast STEPNAME(jump_to_epilog_fast) #define jump_to_next STEPNAME(jump_to_next) #define ret_to_next STEPNAME(ret_to_next) +#define checkCRC STEPNAME(checkCRC) #define doEnterBlock STEPNAME(doEnterBlock) #define doLeaveBlock STEPNAME(doLeaveBlock) #define iret_to_next STEPNAME(iret_to_next) @@ -1615,6 +2043,7 @@ #define mmx_get_reg STEPNAME(mmx_get_reg) #define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty) #define mmx_forget_reg STEPNAME(mmx_forget_reg) +#define fpu_borrow_reg STEPNAME(fpu_borrow_reg) #define mmx_flush_reg_preserve_vtype STEPNAME(mmx_flush_reg_preserve_vtype) #define sse_get_reg STEPNAME(sse_get_reg) #define sse_get_reg_empty STEPNAME(sse_get_reg_empty) @@ -1631,6 +2060,11 @@ #define avx_set_vector_width STEPNAME(avx_set_vector_width) #define avx_load_reg_vector STEPNAME(avx_load_reg_vector) #define avx_store_reg_vector STEPNAME(avx_store_reg_vector) +#define avx_flush_upper_vector STEPNAME(avx_flush_upper_vector) +#define avx_promote_upper STEPNAME(avx_promote_upper) +#define avx_sync_upper_vector STEPNAME(avx_sync_upper_vector) +#define doPreload STEPNAME(doPreload) +#define avx_flush_pending_zero_vector STEPNAME(avx_flush_pending_zero_vector) #define fpu_pushcache STEPNAME(fpu_pushcache) #define fpu_popcache STEPNAME(fpu_popcache) @@ -1664,6 +2098,7 @@ void doEnterBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3); void doLeaveBlock(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3); void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits); void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex); +void checkCRC(dynarec_rv64_t* dyn, int ninst); void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits); void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, int saveflags, int savereg, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w); @@ -1823,8 +2258,8 @@ int sse_setround(dynarec_rv64_t* dyn, int ninst, int s1, int s2); void CacheTransform(dynarec_rv64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3); -void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val); -void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val, int zeroup); +void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val, int s1, int s2); +void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val); int vector_vsetvli(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int vlmul, float multiple); void vector_loadmask(dynarec_rv64_t* dyn, int ninst, int vreg, uint64_t imm, int s1, float multiple); @@ -1872,6 +2307,7 @@ int mmx_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, in int mmx_get_reg_empty_vector(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int a); // forget float register for a MMX reg, create the entry if needed void mmx_forget_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a); +int fpu_borrow_reg(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int reg); void mmx_flush_reg_preserve_vtype(dynarec_rv64_t* dyn, int ninst, int s1, int a); // SSE/SSE2 helpers @@ -1894,11 +2330,54 @@ void sse_purge07cache(dynarec_rv64_t* dyn, int ninst, int s1); // Push current value to the cache void sse_reflect_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a); -// Cache-neutral helpers for Box64's split XMM/YMM register storage. +void avx_flush_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int a, int reg, int next, int dead); +void avx_promote_upper(dynarec_rv64_t* dyn, int ninst, int s1, uint16_t mask); +void avx_sync_upper_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); +void avx_flush_pending_zero_vector(dynarec_rv64_t* dyn, int ninst, int s1, int next); +void doPreload(dynarec_rv64_t* dyn, int ninst); void avx_set_vector_width(dynarec_rv64_t* dyn, int ninst, int s1, int sew, int width); void avx_load_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); void avx_store_reg_vector(dynarec_rv64_t* dyn, int ninst, int s1, int vreg, int a, int width, int sew); +#define emit_mxcsr_raise_invalid(s1) \ + do { \ + LW(s1, xEmu, offsetof(x64emu_t, mxcsr)); \ + ORI(s1, s1, 1); \ + SW(s1, xEmu, offsetof(x64emu_t, mxcsr)); \ + } while (0) + +static inline void sse_set_pending_zero(dynarec_rv64_t* dyn, int a, int pending) +{ + if (dyn->e.ssecache[a].v != -1) + dyn->e.ssecache[a].ymm0 = pending ? 1 : 0; + if (pending) + dyn->e.ymm0 |= (1 << a); + else + dyn->e.ymm0 &= ~(1 << a); +} + +static inline void ymm_live_read(dynarec_rv64_t* dyn, int ninst, int reg) +{ +#if STEP == 0 + dyn->insts[ninst].ymm_upper_use |= (uint16_t)(1 << reg); +#endif +} + +static inline void ymm_live_write(dynarec_rv64_t* dyn, int ninst, int reg) +{ +#if STEP == 0 + dyn->insts[ninst].ymm_upper_def |= (uint16_t)(1 << reg); +#endif +} + +static inline void ymm_live_zero(dynarec_rv64_t* dyn, int ninst, int reg) +{ +#if STEP == 0 + ymm_live_write(dyn, ninst, reg); + dyn->insts[ninst].ymm_zero |= (uint16_t)(1 << reg); +#endif +} + // common coproc helpers // reset the cache with n void fpu_reset_cache(dynarec_rv64_t* dyn, int ninst, int reset_n); @@ -2122,11 +2601,10 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt SLLI(s1, s2, 8); \ J(20); /* end */ \ /* undefined/NaN */ \ - LUI(s1, 4); \ - ADDI(s1, s1, 0b010100000000); \ + MOV32w(s1, 0x4500); \ J(8); /* end */ \ /* equal */ \ - LUI(s1, 4); \ + MOV32w(s1, 0x4000); \ /* end */ \ OR(s3, s3, s1); \ SH(s3, xEmu, offsetof(x64emu_t, sw)); @@ -2268,6 +2746,18 @@ uintptr_t dynarec64_AVX_F3_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintpt } \ } while (0) +#define VECTOR_SPLAT_IMM_S(vreg, imm, s1, s2) \ + do { \ + if (imm == 0) { \ + VXOR_VV(vreg, vreg, vreg, VECTOR_UNMASKED); \ + } else if ((imm & 0xf) == imm) { \ + VMV_V_I(vreg, imm); \ + } else { \ + MOV64xs(s1, imm, s2); \ + VMV_V_X(vreg, s1); \ + } \ + } while (0) + #define VECTOR_LOAD_VMASK(mask, s1, multiple) \ vector_loadmask(dyn, ninst, VMASK, mask, s1, multiple) diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index 9dfc12b3a..e8186bfc2 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -19,7 +19,7 @@ #define READFLAGS_FUSION(A, s1, s2, s3, s4, s5) \ if (BOX64ENV(dynarec_nativeflags) && ninst > 0) { \ int prev = ninst - 1; \ - while (prev && dyn->insts[prev].no_scratch_usage) \ + while (prev && (dyn->insts[prev].no_scratch_usage || dyn->insts[prev].nat_flags_fusion)) \ prev -= 1; \ if (!dyn->insts[prev].nat_flags_nofusion) { \ if ((A) == (X_ZF)) \ @@ -63,6 +63,7 @@ } while (0) #define BARRIER(A) \ if (A != BARRIER_MAYBE) { \ + UP32_READALL(); \ fpu_purgecache(dyn, ninst, 0, x1, x2, x3); \ dyn->insts[ninst].x64.barrier = A; \ } else \ @@ -82,14 +83,17 @@ dyn->inst_sew = dyn->vector_sew; \ dyn->inst_vlmul = VECTOR_LMUL1; \ dyn->inst_vl = 0; \ + dyn->insts[ninst].x64.strongmem = ((box64_wine && VolatileRangesContains(ip)) ? 0 : BOX64DRENV(dynarec_strongmem));\ if (ninst) \ dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr;\ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->insts[ninst].f_exit = dyn->f; \ - dyn->insts[ninst].e = dyn->e; \ - dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; \ +#define INST_EPILOG \ + dyn->insts[ninst].f_exit = dyn->f; \ + dyn->vtype_restore = VECTOR_SEWNA; \ + if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ + dyn->insts[ninst].e = dyn->e; \ + dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; \ dyn->insts[ninst].x64.has_next = (ok > 0) ? 1 : 0; #define INST_NAME(name) #define DEFAULT \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass1.h b/src/dynarec/rv64/dynarec_rv64_pass1.h index 8fd3a9b19..9505ea0a8 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass1.h +++ b/src/dynarec/rv64/dynarec_rv64_pass1.h @@ -20,9 +20,11 @@ dyn->e.barrier = 0; \ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->insts[ninst].e = dyn->e; \ - dyn->insts[ninst].f_exit = dyn->f; \ +#define INST_EPILOG \ + dyn->vtype_restore = VECTOR_SEWNA; \ + if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ + dyn->insts[ninst].e = dyn->e; \ + dyn->insts[ninst].f_exit = dyn->f; \ dyn->insts[ninst].vector_sew_exit = dyn->vector_sew; #define INST_NAME(name) diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h index 304c99bc5..740c11de8 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass2.h +++ b/src/dynarec/rv64/dynarec_rv64_pass2.h @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT #define INIT dyn->native_size = 0 +#define ENDPREFIX \ + dyn->prefixsize = dyn->native_size; \ + dyn->insts[ninst].address = dyn->native_size; \ + dyn->insts[ninst].size = 0 #define FINI \ if (ninst) { \ dyn->insts[ninst].address = (dyn->insts[ninst - 1].address + dyn->insts[ninst - 1].size); \ @@ -15,22 +19,28 @@ dyn->native_size += 4; \ } while (0) #define NEW_INST \ + if (!(ninst > 0 && dyn->insts[ninst].pred_sz == 1 && dyn->insts[ninst].pred[0] == ninst - 1 \ + && dyn->insts[ninst - 1].x64.has_next && !dyn->insts[ninst - 1].x64.jmp \ + && !(dyn->insts[ninst - 1].x64.barrier & BARRIER_FLOAT) && !dyn->insts[ninst - 1].x64.has_callret)) { \ + dyn->inst_sew = dyn->insts[ninst].vector_sew_entry; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; \ + } \ dyn->vector_sew = dyn->insts[ninst].vector_sew_entry; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; \ if (ninst) { \ dyn->insts[ninst].address = (dyn->insts[ninst - 1].address + dyn->insts[ninst - 1].size); \ dyn->insts_size += 1 + ((dyn->insts[ninst - 1].x64.size > (dyn->insts[ninst - 1].size / 4)) ? dyn->insts[ninst - 1].x64.size : (dyn->insts[ninst - 1].size / 4)) / 15; \ dyn->insts[ninst].ymm0_pass2 = dyn->ymm_zero; \ } \ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->insts[ninst].epilog = dyn->native_size; \ - dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; +#define INST_EPILOG \ + dyn->insts[ninst].epilog = dyn->native_size; \ + if (dyn->vtype_restore != VECTOR_SEWNA) { \ + avx_set_vector_width(dyn, ninst, x1, dyn->vtype_restore, 16); \ + dyn->vtype_restore = VECTOR_SEWNA; \ + } \ + if (dyn->insts[ninst].vec_used) sse_sync_all_cache_types(&dyn->e); \ + dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; #define INST_NAME(name) #define TABLE64(A, V) \ do { \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h index ad9eb262d..0db21da8e 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass3.h +++ b/src/dynarec/rv64/dynarec_rv64_pass3.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT #define INIT +#define ENDPREFIX dyn->insts[ninst].size2 = 0 #define FINI \ if (ninst) \ addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4); \ @@ -18,20 +19,26 @@ if (dyn->need_dump && dyn->need_dump != 3) dynarec_log(LOG_NONE, __VA_ARGS__); \ } while (0) #define NEW_INST \ + if (!(ninst > 0 && dyn->insts[ninst].pred_sz == 1 && dyn->insts[ninst].pred[0] == ninst - 1 \ + && dyn->insts[ninst - 1].x64.has_next && !dyn->insts[ninst - 1].x64.jmp \ + && !(dyn->insts[ninst - 1].x64.barrier & BARRIER_FLOAT) && !dyn->insts[ninst - 1].x64.has_callret)) { \ + dyn->inst_sew = dyn->insts[ninst].vector_sew_entry; \ + dyn->inst_vlmul = VECTOR_LMUL1; \ + dyn->inst_vl = 0; \ + } \ dyn->vector_sew = dyn->insts[ninst].vector_sew_entry; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; \ if (ninst) { \ addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst - 1].x64.size, dyn->insts[ninst - 1].size / 4); \ dyn->insts[ninst].ymm0_pass3 = dyn->ymm_zero; \ } \ + if (ninst && dyn->insts[ninst - 1].vec_used) sse_sync_all_cache_types(&dyn->e); \ AREFLAGSNEEDED() -#define INST_EPILOG \ - dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; \ - dyn->inst_sew = dyn->vector_sew; \ - dyn->inst_vlmul = VECTOR_LMUL1; \ - dyn->inst_vl = 0; +#define INST_EPILOG \ + if (dyn->vtype_restore != VECTOR_SEWNA) { \ + avx_set_vector_width(dyn, ninst, x1, dyn->vtype_restore, 16); \ + dyn->vtype_restore = VECTOR_SEWNA; \ + } \ + dyn->vector_sew = dyn->insts[ninst].vector_sew_exit; #define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex) #define TABLE64(A, V) \ diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 7877a7a02..8f5075fb9 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -23,6 +23,8 @@ typedef struct box64env_s box64env_t; #define EXT_CACHE_XMMW 8 #define EXT_CACHE_XMMR 9 #define EXT_CACHE_MMV 10 +#define EXT_CACHE_YMMW 11 +#define EXT_CACHE_YMMR 12 #define EXT_CACHE_OLD_SD 0 #define EXT_CACHE_OLD_SS 1 @@ -30,10 +32,11 @@ typedef struct box64env_s box64env_t; #define EXT_CACHE_OLD_XMMR 3 typedef union ext_cache_s { - int8_t v; + int16_t v; struct { - uint8_t t:4; // reg type - uint8_t n:4; // reg number + uint16_t t : 4; // reg type + uint16_t n : 4; // reg number + uint16_t y : 1; // register holds the whole ymm }; } ext_cache_t; @@ -46,12 +49,14 @@ typedef union mmx_cache_s { } mmx_cache_t; typedef union sse_cache_s { - int16_t v; + int32_t v; struct { - uint16_t reg : 13; - uint16_t vector : 1; - uint16_t single : 1; - uint16_t write : 1; + uint32_t reg : 13; + uint32_t vector : 1; + uint32_t single : 1; + uint32_t write : 1; + uint32_t ymm : 1; // register holds the whole ymm + uint32_t ymm0 : 1; // architectural upper half of the ymm is zero }; } sse_cache_t; @@ -90,6 +95,7 @@ typedef struct extcache_s { int8_t x87stack; // cache stack counter int8_t mmxcount; // number of mmx register used (not both mmx and x87 at the same time) int8_t fpu_scratch; // scratch counter + uint16_t ymm0; // upper 128bits are zero and not held in memory } extcache_t; typedef enum flagcache_s { @@ -101,6 +107,10 @@ typedef enum flagcache_s { typedef struct callret_s callret_t; +#define RSP_CLASS_BARRIER 0 +#define RSP_CLASS_PUSH 1 +#define RSP_CLASS_POP 2 + typedef struct instruction_rv64_s { instruction_x64_t x64; uintptr_t address; // (start) address of the riscv emitted instruction @@ -111,6 +121,7 @@ typedef struct instruction_rv64_s { int *pred; // predecessor array uintptr_t mark[4]; uintptr_t markf[2]; + uintptr_t markfnan; uintptr_t markseg; uintptr_t marklock; uintptr_t marklock2; @@ -130,6 +141,7 @@ typedef struct instruction_rv64_s { uint8_t nat_flags_carry:1; uint8_t nat_flags_sign:1; uint8_t nat_flags_needsign:1; + uint8_t nat_flags_needunsigned:1; uint8_t unaligned:1; // this opcode can be re-generated for unaligned special case uint8_t x87precision:1; // this opcode can handle x87pc uint8_t no_scratch_usage:1; // this opcode does not use scratch register @@ -141,6 +153,29 @@ typedef struct instruction_rv64_s { flagcache_t f_entry; // flags status before the instruction begin uint8_t vector_sew_entry; // sew status before the instruction begin uint8_t vector_sew_exit; // sew status at the end of instruction + int16_t rsp_entry; // pending rsp offset at entry + int16_t rsp_flush; // rsp offset to emit right after this push/pop + uint8_t rsp_merge:1; // this push/pop is emitted with merged rsp offset + uint8_t rsp_class:2; // RSP_* of this opcode (marked by the opcode handler) + uint8_t rsp_span; // push/pop depth of this opcode in bytes (0 = one delta, PUSHA/POPA = 32) + uint16_t up32_read; // bitmask of GPRs whose upper 32 bits are read by this instruction + uint16_t up32_write64; // bitmask of GPRs written as 64-bit by this instruction (upper 32 become defined) + uint16_t up32_write32; // bitmask of GPRs written as 32-bit by this instruction + uint16_t up32_zero; // bitmask of GPRs guaranteed to be zero-extended at instruction exit + uint16_t up32_skip; // bitmask of GPRs where the implicit zero-up after a 32-bit write can be skipped + uint16_t up32_pending; // bitmask of GPRs whose upper 32 bits are stale at entry to this instruction + uint32_t vec_used; // bitmask of XMM/YMM registers touched by this instruction + uint16_t vec_read; // bitmask of XMM/YMM registers read by this instruction + uint16_t vec_write_full; // bitmask of XMM/YMM registers fully (both halves) written by this instruction + uint32_t preload_xmmymm; // registers to preload at this instruction + int preload_from; // last instruction of the region that uses them + uint16_t ymm_upper_use; // bitmask of YMM upper halves read by this instruction + uint16_t ymm_upper_def; // bitmask of YMM upper halves written by this instruction + uint16_t ymm_upper_live; // bitmask of YMM upper halves live after this instruction + uint16_t ymm_zero; // bitmask of YMM upper halves deferred-zeroed by this instruction + uint16_t ymm_pending; // bitmask of pending YMM upper-half zeros on entry to this instruction + uint8_t ymm_pending_materialized; // pending YMM upper-half zeros are materialized before this instruction runs + uint16_t promote_ymm; // per-instruction bitmask of registers to promote } instruction_rv64_t; typedef struct dynarec_rv64_s { @@ -181,13 +216,16 @@ typedef struct dynarec_rv64_s { int32_t forward_size; // size at the forward point int forward_ninst; // ninst at the forward point uint16_t ymm_zero; // bitmap of ymm to zero at purge + uint8_t pending_zero_flushed; uint8_t always_test; uint8_t abort; uint8_t vector_sew; // current sew status uint8_t vector_eew; // current effective sew status, should only be used after SET_ELEMENT_WIDTH uint8_t inst_sew; // sew inside current instruction, for vsetvli elimination + uint16_t purge_dead_vector; // SIMD regs whose value is dead at the purge target (skip write-back) uint8_t inst_vl; // vl inside current instruction, for vsetvli elimination uint8_t inst_vlmul; // vlmul inside current instruction + uint8_t vtype_restore; uint8_t is_file_mapped; // if the memory is a mapped file (probably binary, not a memory) void* gdbjit_block; uint32_t need_x87check; // x87 low precision check @@ -199,10 +237,37 @@ typedef struct dynarec_rv64_s { } dynarec_rv64_t; // v0 is hardware wired to vector mask register, which should be always reserved -// convert idx (0..23) to reg index (10..31 1..2) -#define EXTREG(A) (((A) + 10 + ((A) > 21)) & 31) -// convert reg index (10..31 1..2) to idx (0..23) -#define EXTIDX(A) (((A) - 10 - ((A) < 3)) & 31) +// convert idx (0..23) to reg index +#define EXTREG(A) (((A) < 16) ? (16 + (A)) : ((A) - 8)) +// convert reg index (8..31) to idx (0..23) +#define EXTIDX(A) (((A) >= 16) ? ((A) - 16) : ((A) + 8)) + +#define XMM0 0 +#define X870 (XMM0 + 16) +#define EMM0 (XMM0 + 16) +#define VREG(A) EXTREG(XMM0 + (A)) + +static inline void sse_sync_cache_type(extcache_t* cache, int a) +{ + sse_cache_t* e = &cache->ssecache[a]; + if (e->v == -1) + return; + if (!e->vector) { + cache->extcache[EXTIDX(e->reg)].t = e->single ? EXT_CACHE_SS : EXT_CACHE_SD; + return; + } + int dirty = e->write || e->ymm0; + if (e->ymm) + cache->extcache[EXTIDX(e->reg)].t = dirty ? EXT_CACHE_YMMW : EXT_CACHE_YMMR; + else + cache->extcache[EXTIDX(e->reg)].t = dirty ? EXT_CACHE_XMMW : EXT_CACHE_XMMR; +} + +static inline void sse_sync_all_cache_types(extcache_t* cache) +{ + for (int i = 0; i < 16; ++i) + sse_sync_cache_type(cache, i); +} void add_next(dynarec_rv64_t *dyn, uintptr_t addr); uintptr_t get_closest_next(dynarec_rv64_t *dyn, uintptr_t addr); diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 53b9de273..9fb6a3dd0 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -11,8 +11,10 @@ #define SPLIT12(A) ((A) & 0xfff) // MOV64x/MOV32w is quite complex, so use a function for this -#define MOV64x(A, B) rv64_move64(dyn, ninst, A, B) -#define MOV32w(A, B) rv64_move32(dyn, ninst, A, B, 1) +#define MOV64x(A, B) rv64_move64(dyn, ninst, A, B, -1, -1) +#define MOV64xs(A, B, S1) rv64_move64(dyn, ninst, A, B, S1, -1) +#define MOV64xss(A, B, S1, S2) rv64_move64(dyn, ninst, A, B, S1, S2) +#define MOV32w(A, B) rv64_move32(dyn, ninst, A, (int32_t)(B)) #define MOV64xw(A, B) \ do { \ if (rex.w) { \ @@ -114,20 +116,20 @@ // rd = rs1 + rs2 #define ADDxw(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b000, rd, rex.w ? 0b0110011 : 0b0111011)) // rd = rs1 + rs2 -#define ADDz(rd, rs1, rs2) \ - do { \ - if (!rex.is32bits) { \ - ADD(rd, rs1, rs2); \ - } else { \ - ADDW(rd, rs1, rs2); \ - ZEROUP(rd); \ - } \ +#define ADDz(rd, rs1, rs2) \ + do { \ + if (!rex.is32bits) { \ + ADD(rd, rs1, rs2); \ + } else { \ + ADDW(rd, rs1, rs2); \ + ZEROUP32_RESULT(rd); \ + } \ } while (0) #define ADDy(rd, rs1, rs2) \ do { \ if (rex.is32bits || rex.is67) { \ ADDW(rd, rs1, rs2); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } else { \ ADD(rd, rs1, rs2); \ } \ @@ -148,14 +150,14 @@ // rd = rs1 - rs2 #define SUBxw(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b000, rd, rex.w ? 0b0110011 : 0b0111011)) // rd = rs1 - rs2 -#define SUBz(rd, rs1, rs2) \ - do { \ - if (!rex.is32bits) { \ - SUB(rd, rs1, rs2); \ - } else { \ - SUB(rd, rs1, rs2); \ - ZEROUP(rd); \ - } \ +#define SUBz(rd, rs1, rs2) \ + do { \ + if (!rex.is32bits) { \ + SUB(rd, rs1, rs2); \ + } else { \ + SUB(rd, rs1, rs2); \ + ZEROUP32_RESULT(rd); \ + } \ } while (0) // rd = rs1<>rs2 logical #define SRL(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b101, rd, 0b0110011)) @@ -519,6 +521,64 @@ PUSH1(reg); \ } +#define PUSH1mz(reg) \ + do { \ + if ((reg) != xRSP) \ + dyn->insts[ninst].rsp_class = RSP_CLASS_PUSH; \ + if (dyn->insts[ninst].rsp_merge) { \ + int entry = dyn->insts[ninst].rsp_entry; \ + int flush = dyn->insts[ninst].rsp_flush; \ + int imm5 = flush / (rex.is32bits ? 4 : 8); \ + if (flush && !entry) { \ + if (rex.is32bits) \ + PUSH1_32(reg); \ + else \ + PUSH1(reg); \ + } else if (flush && cpuext.xtheadmemidx && imm5 >= -16 && imm5 <= 15) { \ + if (rex.is32bits) \ + TH_SWIB(reg, xRSP, imm5, 2); \ + else \ + TH_SDIB(reg, xRSP, imm5, 3); \ + } else { \ + if (rex.is32bits) \ + SW(reg, xRSP, entry - 4); \ + else \ + SD(reg, xRSP, entry - 8); \ + if (flush) ADDI(xRSP, xRSP, flush); \ + } \ + } else if (rex.is32bits) { \ + PUSH1_32(reg); \ + } else { \ + PUSH1(reg); \ + } \ + } while (0) + +#define POP1mz(reg) \ + do { \ + if ((reg) != xRSP) \ + dyn->insts[ninst].rsp_class = RSP_CLASS_POP; \ + if (dyn->insts[ninst].rsp_merge) { \ + int entry = dyn->insts[ninst].rsp_entry; \ + int flush = dyn->insts[ninst].rsp_flush; \ + if (flush && !entry) { \ + if (rex.is32bits) \ + POP1_32(reg); \ + else \ + POP1(reg); \ + } else { \ + if (rex.is32bits) \ + LWU(reg, xRSP, entry); \ + else \ + LD(reg, xRSP, entry); \ + if (flush) ADDI(xRSP, xRSP, flush); \ + } \ + } else if (rex.is32bits) { \ + POP1_32(reg); \ + } else { \ + POP1(reg); \ + } \ + } while (0) + #define PUSH1_16(reg) \ do { \ if (cpuext.xtheadmemidx && reg != xRSP) { \ @@ -543,10 +603,18 @@ #define FENCE_R_RW() EMIT(FENCE_gen(2, 3)) #define FENCE_W_W() EMIT(FENCE_gen(1, 1)) #define FENCE_RW_RW() EMIT(FENCE_gen(3, 3)) +#define FENCE_TSO() EMIT(FENCE_gen(3, 3) | (8u << 28)) #define DMB_ISH() FENCE_RW_RW() #define DMB_ISHLD() FENCE_R_RW() #define DMB_ISHST() FENCE_W_W() +#define DMB_TSO() \ + do { \ + if (cpuext.vector && !cpuext.xtheadvector) \ + FENCE_TSO(); \ + else \ + FENCE_RW_RW(); \ + } while (0) #define FENCE_I_gen() ((0b001 << 12) | 0b0001111) #define FENCE_I() EMIT(FENCE_I_gen()) @@ -601,14 +669,14 @@ ADDI(rd, rs1, imm12); \ } else { \ ADDIW(rd, rs1, imm12); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } \ } while (0) #define ADDIy(rd, rs1, imm12) \ do { \ if (rex.is32bits || rex.is67) { \ ADDIW(rd, rs1, imm12); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } else { \ ADDI(rd, rs1, imm12); \ } \ @@ -629,7 +697,7 @@ #define ADDSLy(rd, rs1, rs2, imm2, scratch) \ if (rex.is32bits || rex.is67) { \ ADDSL(rd, rs1, rs2, imm2, scratch); \ - ZEROUP(rd); \ + ZEROUP32_RESULT(rd); \ } else { \ ADDSL(rd, rs1, rs2, imm2, scratch); \ } @@ -649,7 +717,8 @@ SLL(rd, rs1, rs2); \ } else { \ SLLW(rd, rs1, rs2); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) @@ -659,7 +728,8 @@ SRL(rd, rs1, rs2); \ } else { \ SRLW(rd, rs1, rs2); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) @@ -669,7 +739,8 @@ SRA(rd, rs1, rs2); \ } else { \ SRAW(rd, rs1, rs2); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) @@ -682,14 +753,16 @@ SLLI(rd, rs1, imm); \ } else { \ SLLIW(rd, rs1, imm); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) #define SLLIy(rd, rs1, imm) \ do { \ if (rex.is32bits || rex.is67) { \ SLLIW(rd, rs1, imm); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } else { \ SLLI(rd, rs1, imm); \ } \ @@ -697,14 +770,17 @@ // Shift Right Logical Immediate, 32-bit, sign-extended #define SRLIW(rd, rs1, imm5) EMIT(I_type(imm5, rs1, 0b101, rd, 0b0011011)) // Shift Right Logical Immediate -#define SRLIxw(rd, rs1, imm) \ - do { \ - if (rex.w) { \ - SRLI(rd, rs1, imm); \ - } else { \ - SRLIW(rd, rs1, imm); \ - if ((imm) == 0) ZEROUP(rd); \ - } \ +#define SRLIxw(rd, rs1, imm) \ + do { \ + if (rex.w) { \ + SRLI(rd, rs1, imm); \ + } else { \ + SRLIW(rd, rs1, imm); \ + if ((imm) == 0) { \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ + } \ + } \ } while (0) // Shift Right Arithmetic Immediate, 32-bit, sign-extended #define SRAIW(rd, rs1, imm5) EMIT(I_type((imm5) | (0b0100000 << 5), rs1, 0b101, rd, 0b0011011)) @@ -715,7 +791,8 @@ SRAI(rd, rs1, imm); \ } else { \ SRAIW(rd, rs1, imm); \ - ZEROUP(rd); \ + UP32_WRITE32(rd); \ + ZEROUP_RESULT(rd); \ } \ } while (0) @@ -1134,14 +1211,14 @@ } // Insert low 16bits in rs to low 16bits of rd -#define INSH(rd, rs, s1, s2, init_s1, zexth_rs) \ - if (init_s1) LUI(s1, 0xffff0); \ - AND(rd, rd, s1); \ - if (zexth_rs) { \ - ZEXTH(s2, rs); \ - OR(rd, rd, s2); \ - } else { \ - OR(rd, rd, rs); \ +#define INSH(rd, rs, s1, s2, init_s1, zexth_rs) \ + if (init_s1) MOV64x(s1, 0xFFFFFFFFFFFF0000); \ + AND(rd, rd, s1); \ + if (zexth_rs) { \ + ZEXTH(s2, rs); \ + OR(rd, rd, s2); \ + } else { \ + OR(rd, rd, rs); \ } // Insert low 16bits in rs to low 16bits of rd @@ -1224,7 +1301,7 @@ OR(s1, s1, s3); \ OR(s1, s1, s4); \ SLLIW(s3, rs, 8); \ - LUI(s2, 0xff0); \ + MOV32w(s2, 0xFF0000); \ AND(s3, s3, s2); \ OR(rd, s1, s3); \ } \ @@ -1260,15 +1337,14 @@ // Single-bit Set (Immediate) #define BSETI_(rd, rs1, imm) EMIT(R_type(0b0010100, imm, rs1, 0b001, rd, 0b0010011)) // Single-bit Set (Immediate), with fallback (s0 is used as a scratch register) -#define BSETI(rd, rs1, imm, s0) \ - do { \ - if (cpuext.zbs) \ - BSETI_(rd, rs1, imm); \ - else { \ - ADDI(s0, xZR, 1); \ - SLLI(s0, s0, (imm)); \ - OR(rd, rs1, s0); \ - } \ +#define BSETI(rd, rs1, imm, s0) \ + do { \ + if (cpuext.zbs) \ + BSETI_(rd, rs1, imm); \ + else { \ + MOV64x(s0, 1ULL << (imm)); \ + OR(rd, rs1, s0); \ + } \ } while (0) // Single-bit Extract (Register) diff --git a/src/dynarec/rv64/rv64_lock.S b/src/dynarec/rv64/rv64_lock.S index a27694af3..ce293887e 100644 --- a/src/dynarec/rv64/rv64_lock.S +++ b/src/dynarec/rv64/rv64_lock.S @@ -26,6 +26,10 @@ .global rv64_lock_get_b .global rv64_lock_get_d .global rv64_lock_get_dd +.global rv64_crc +.global rv64_crc_autocrc +.global rv64_crc_zbc +.global rv64_crc_autocrc_zbc rv64_lock_xchg_dd: // address is a0, value is a1, return old value in a0 @@ -271,3 +275,134 @@ rv64_lock_get_dd: fence rw, rw ld a0, 0(a0) ret + +rv64_crc: + // a0 = address, a1 = length, returns uint32_t hash in a0 + li a2, 0xcbf29ce484222325 + li a7, 0x100000001b3 + li a3, 8 +1: + bltu a1, a3, 2f + ld a4, 0(a0) + xor a2, a2, a4 + mul a2, a2, a7 + addi a0, a0, 8 + addi a1, a1, -8 + bnez a1, 1b +2: + beqz a1, 3f + lbu a4, 0(a0) + xor a2, a2, a4 + mul a2, a2, a7 + addi a0, a0, 1 + addi a1, a1, -1 + bnez a1, 2b +3: + mv a0, a2 + addiw a0, a0, 0 + ret + +rv64_crc_autocrc: + // t3 = address, t4 = length, t2 = hash, t6 is preserved + li t2, 0xcbf29ce484222325 + li a7, 0x100000001b3 + li t5, 8 +1: + bltu t4, t5, 2f + ld t1, 0(t3) + xor t2, t2, t1 + mul t2, t2, a7 + addi t3, t3, 8 + addi t4, t4, -8 + bnez t4, 1b +2: + beqz t4, 3f + lbu t1, 0(t3) + xor t2, t2, t1 + mul t2, t2, a7 + addi t3, t3, 1 + addi t4, t4, -1 + bnez t4, 2b +3: + slli t2, t2, 32 + srli t2, t2, 32 + ret + + .option arch, +zbc +rv64_crc_zbc: + // a0 = address, a1 = length, returns uint32_t CRC32C in a0 + li a2, 0 + li a3, 8 +1: + bltu a1, a3, 2f + slli a2, a2, 32 + srli a2, a2, 32 + ld a4, 0(a0) + xor a4, a4, a2 + li a7, 0x4869EC38DEA713F1 + clmul a4, a4, a7 + li a7, 0x105EC76F1 + clmulh a4, a4, a7 + mv a2, a4 + addi a0, a0, 8 + addi a1, a1, -8 + bnez a1, 1b +2: + beqz a1, 3f + slli a2, a2, 32 + srli a2, a2, 32 + lbu a4, 0(a0) + xor a4, a4, a2 + slli a4, a4, 56 + li a7, 0x4869EC38DEA713F1 + clmul a4, a4, a7 + li a7, 0x105EC76F1 + clmulh a4, a4, a7 + srli a3, a2, 8 + xor a2, a4, a3 + addi a0, a0, 1 + addi a1, a1, -1 + bnez a1, 2b +3: + mv a0, a2 + addiw a0, a0, 0 + ret + +rv64_crc_autocrc_zbc: + // t3 = address, t4 = length, t2 = CRC32C, t6 is preserved + li t2, 0 + li t5, 8 +1: + bltu t4, t5, 2f + slli t2, t2, 32 + srli t2, t2, 32 + ld t1, 0(t3) + xor t1, t1, t2 + li a7, 0x4869EC38DEA713F1 + clmul t1, t1, a7 + li a7, 0x105EC76F1 + clmulh t1, t1, a7 + mv t2, t1 + addi t3, t3, 8 + addi t4, t4, -8 + bnez t4, 1b +2: + beqz t4, 3f + slli t2, t2, 32 + srli t2, t2, 32 + lbu t1, 0(t3) + xor t1, t1, t2 + slli t1, t1, 56 + li a7, 0x4869EC38DEA713F1 + clmul t1, t1, a7 + li a7, 0x105EC76F1 + clmulh t1, t1, a7 + srli t5, t2, 8 + xor t2, t1, t5 + addi t3, t3, 1 + addi t4, t4, -1 + bnez t4, 2b +3: + slli t2, t2, 32 + srli t2, t2, 32 + ret diff --git a/src/dynarec/rv64/rv64_mapping.h b/src/dynarec/rv64/rv64_mapping.h index 814ad87e8..d5c16876c 100644 --- a/src/dynarec/rv64/rv64_mapping.h +++ b/src/dynarec/rv64/rv64_mapping.h @@ -69,6 +69,8 @@ x31 t6 x6 Temporary Scratch // convert a x86 register to native according to the register mapping #define TO_NAT(A) (((uint8_t[]) { 16, 13, 12, 24, 9, 8, 11, 10, 14, 15, 26, 27, 18, 19, 20, 21 })[(A)]) +// convert a native register to x86 GPR (or -1 if not a GPR), reverse of TO_NAT +#define TO_X64(A) (((int8_t[]) { -1, -1, -1, -1, -1, -1, -1, -1, 5, 4, 7, 6, 2, 1, 8, 9, 0, -1, 12, 13, 14, 15, -1, -1, 3, -1, 10, 11, -1, -1, -1, -1 })[(A)]) #define IS_GPR(A) (((uint8_t[]) { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0 })[(A)]) #define IS_SCRATCH(A) (((uint8_t[]) { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 })[(A)]) diff --git a/src/dynarec/rv64/rv64_mov_imm.c b/src/dynarec/rv64/rv64_mov_imm.c new file mode 100644 index 000000000..0b0ca101a --- /dev/null +++ b/src/dynarec/rv64/rv64_mov_imm.c @@ -0,0 +1,746 @@ +// SPDX-License-Identifier: MIT + +/* + * 1. rv64_mov_seq64() and rv64_mov_seq32() + * + * These two functions try a number of standard tricks and keep the best result. + * "Best" means the fewest instructions; if two results use the same number of instructions, + * the one with the shorter dependency chain wins, because it has less latency. + * + * Some of the tricks are: + * - single ADDI for values that fit in 12 signed bits + * - LUI + ADDIW for ordinary 32-bit values + * - BSETI when only one or a few bits are set + * - building -1 and shifting it for simple masks + * - shifting the value, building the shifted value and shifting it back + * - splitting the value into a low half and a high half, building each half and joining them with a shift and an ADD + * - optional Zba / Zbs / Zbb instructions (SH1ADD, BCLRI, RORI, SLLIUW, ...) when the CPU has those extensions + * + * Some tricks build the value in pieces: + * they ask for a sequence for a sub-value and then add the instruction that joins the pieces together. + * The expensive recursive candidates stop at RV64_MOV_MAXDEPTH (currently 2), RV64_MOV_BUDGET caps the total work, + * and rv64_mov_min_ops64() skips branches that cannot improve the best result. + * + * 2. rv64_mov_emit_seq() + * + * This is the emitter, it turns the list that step 1 returns into real RISC-V instructions, + * using the destination register and the scratch registers that the caller provided. + * + * 3. rv64_mov_cache_get() and rv64_mov_cache_put() + * + * A small per-thread cache table remembers up to 1024 answers. + * An entry is identified by the value, the number of scratch registers used and whether this is a 32-bit or a 64-bit move. + * Very long sequences (more than 8 steps) are not cached. + */ +#include +#include + +#include "rv64_mov_imm.h" +#include "rv64_emitter.h" + +static int rv64_mov_ctz64(uint64_t x) { return x ? __builtin_ctzll(x) : 64; } +static int rv64_mov_clz64(uint64_t x) { return x ? __builtin_clzll(x) : 64; } +static int rv64_mov_popcnt64(uint64_t x) { return __builtin_popcountll(x); } + +static int32_t rv64_mov_sext12(uint32_t x) { return (int32_t)(((x & 0xfffu) ^ 0x800u) - 0x800u); } + +static int rv64_mov_fits12(uint64_t v) +{ + int64_t s = (int64_t)v; + return s >= -2048 && s <= 2047; +} + +static int rv64_mov_fits32(uint64_t v) +{ + int64_t s = (int64_t)v; + return s >= -0x80000000LL && s <= 0x7fffffffLL; +} + +static int rv64_mov_min_ops64(const rv64_movctx_t* ctx, uint64_t v) +{ + if (rv64_mov_fits12(v)) return 1; + if (ctx->caps.zbs && v && !(v & (v - 1))) return 1; + if (rv64_mov_fits32(v) && !(v & 0xfff)) return 1; + if (v && !(v & (v + 1))) return 2; + if (ctx->caps.zbs) { + int c = rv64_mov_popcnt64(v); + if (c && c <= 4) return c; + int z = rv64_mov_popcnt64(~v); + if (z && z <= 3) return 1 + z; + } + if (rv64_mov_fits32(v)) return 2; + int t = rv64_mov_ctz64(v); + if (v && t > 0 && (v >> t) == (~UINT64_C(0) >> t)) return 2; + if (v && t >= 12 && (v >> t) < 0x100000 && (ctx->caps.zba || (v >> t) < 0x80000)) return 2; + return 3; +} + +static void rv64_mov_seq_zero(rv64_mov_seq_t* p) +{ + p->n = 0; + p->depth = 0; + p->overflow = 0; +} + +static void rv64_mov_seq_copy(rv64_mov_seq_t* dst, const rv64_mov_seq_t* src) +{ + dst->n = src->n; + dst->depth = src->depth; + dst->overflow = src->overflow; + memcpy(dst->op, src->op, src->n * sizeof(rv64_movop_t)); +} + +static void rv64_mov_seq_add(rv64_mov_seq_t* p, uint8_t op, uint8_t rd, uint8_t rs, uint8_t rs2, int32_t imm, int depth) +{ + if (p->n >= RV64_MOV_MAXOPS) { + p->overflow = 1; + return; + } + p->op[p->n].op = op; + p->op[p->n].rd = rd; + p->op[p->n].rs = rs; + p->op[p->n].rs2 = rs2; + p->op[p->n].imm = imm; + p->n++; + if (depth > p->depth) p->depth = (uint8_t)depth; +} + +static void rv64_mov_seq_rename(rv64_mov_seq_t* p, uint8_t from, uint8_t to) +{ + int i; + for (i = 0; i < p->n; ++i) { + if (p->op[i].rd == from) p->op[i].rd = to; + if (p->op[i].rs == from) p->op[i].rs = to; + if (p->op[i].rs2 == from) p->op[i].rs2 = to; + } +} + +static void rv64_mov_seq_concat(rv64_mov_seq_t* dst, const rv64_mov_seq_t* src) +{ + int i; + int base = dst->depth; + if (dst->overflow || src->overflow) { + dst->overflow = 1; + return; + } + for (i = 0; i < src->n; ++i) { + if (dst->n >= RV64_MOV_MAXOPS) { + dst->overflow = 1; + return; + } + dst->op[dst->n] = src->op[i]; + dst->n++; + } + if (src->depth > base) base = src->depth; + dst->depth = (uint8_t)base; +} + +typedef struct rv64_movbest_s { + int cost; + int depth; + rv64_mov_seq_t seq; +} rv64_movbest_t; + +static void rv64_mov_best_try(rv64_movbest_t* best, const rv64_mov_seq_t* p) +{ + if (!p->n || p->n > RV64_MOV_MAXOPS || p->overflow) return; + if (p->n < best->cost || (p->n == best->cost && p->depth < best->depth)) { + best->cost = p->n; + best->depth = p->depth; + rv64_mov_seq_copy(&best->seq, p); + } +} + +static void rv64_mov_best_try1(rv64_movbest_t* best, const rv64_mov_seq_t* sub, + uint8_t op, uint8_t rd, uint8_t rs, int32_t imm) +{ + rv64_mov_seq_t p; + if (!sub->n || sub->n + 1 > RV64_MOV_MAXOPS || sub->overflow) return; + rv64_mov_seq_copy(&p, sub); + rv64_mov_seq_add(&p, op, rd, rs, 0, imm, sub->depth + 1); + rv64_mov_best_try(best, &p); +} + + +static int rv64_mov_seq_high(rv64_movctx_t* ctx, uint64_t hi, int sh, int depth, int nscratch, rv64_mov_seq_t* out) +{ + rv64_mov_seq_t sub; + rv64_movbest_t best; + best.cost = 99; + best.depth = 99; + best.seq.n = 0; + best.seq.depth = 0; + best.seq.overflow = 0; + + if (rv64_mov_seq64(ctx, hi, depth, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, sh); + + if (hi < 0x100000000ULL && (hi & 0x80000000ULL) && sh >= 32) { + if (rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)hi, depth, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, sh); + } + + if (hi && hi < 0x100000ULL && sh >= 12) { + rv64_mov_seq_t p; + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, (int32_t)hi, 1); + if (hi < 0x80000ULL) { + if (sh > 12) rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh - 12, 2); + rv64_mov_best_try(&best, &p); + } else if (ctx->caps.zba && sh > 12) { + rv64_mov_seq_add(&p, RV64_MOV_SLLIUW, RV64_MOV_DST, 0, 0, sh - 12, 2); + rv64_mov_best_try(&best, &p); + } + } + + if (!best.cost) return 0; + rv64_mov_seq_copy(out, &best.seq); + return out->n; +} + +int rv64_mov_seq64(rv64_movctx_t* ctx, uint64_t v, int depth, int nscratch, rv64_mov_seq_t* out) +{ + rv64_movbest_t best; + best.cost = 99; + best.depth = 99; + best.seq.n = 0; + best.seq.depth = 0; + best.seq.overflow = 0; + rv64_mov_seq_t p, sub; + int64_t sv = (int64_t)v; + int t, n; + + if (rv64_mov_fits12(v)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)sv, 1); + rv64_mov_best_try(&best, &p); + } + + if (rv64_mov_fits32(v) && !rv64_mov_fits12(v)) { + uint32_t vv = (uint32_t)v; + int32_t hi20 = (int32_t)(((uint64_t)vv + 0x800) >> 12) & 0xfffff; + int32_t lo12 = rv64_mov_sext12(vv); + rv64_mov_seq_zero(&p); + if (!lo12) { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + } else if (!hi20) { + rv64_mov_seq_add(&p, RV64_MOV_ADDIW, RV64_MOV_DST, 0, 0, lo12, 1); + } else { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + rv64_mov_seq_add(&p, RV64_MOV_ADDIW, RV64_MOV_DST, 0, 0, lo12, 2); + } + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v && !(v & (v - 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(v), 1); + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v && rv64_mov_popcnt64(v) <= 4) { + uint64_t z = v; + int c = 0; + rv64_mov_seq_zero(&p); + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + rv64_mov_best_try(&best, &p); + } + + if (v && !(v & (v + 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, rv64_mov_clz64(v), 2); + rv64_mov_best_try(&best, &p); + } + + t = rv64_mov_ctz64(v); + if (v && t > 0 && t < 64 && (v >> t) == (~UINT64_C(0) >> t)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, t, 2); + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v != ~UINT64_C(0)) { + int k = rv64_mov_ctz64(~v); + if ((v | (UINT64_C(1) << k)) == ~UINT64_C(0) && !rv64_mov_fits12(v)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_BCLRI, RV64_MOV_DST, 0, 0, k, 2); + rv64_mov_best_try(&best, &p); + } + } + + if (ctx->caps.zbs && best.cost > 2) { + uint64_t zeros = ~v; + n = rv64_mov_popcnt64(zeros); + if (n > 0 && n <= 3) { + uint64_t z = zeros; + int c = 1; + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BCLRI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + rv64_mov_best_try(&best, &p); + } + } + + if (ctx->caps.zbs && best.cost > 1) { + uint32_t low12 = (uint32_t)v & 0xfff; + int32_t cand[2]; + int ncand = 0; + if (v & 0x7ff) cand[ncand++] = (int32_t)(v & 0x7ff); + if (low12) { + int32_t a = rv64_mov_sext12(low12); + if (a >= 0 || (((uint64_t)v - (uint64_t)(int64_t)a) & 0x7ffff000ULL)) + cand[ncand++] = a; + } + for (int i = 0; i < ncand; ++i) { + int32_t a = cand[i]; + uint64_t w = v - (uint64_t)(int64_t)a; + uint64_t lui_part, rest, z; + int c = 0; + if (w & 0xfff) continue; + lui_part = w & 0x7ffff000ULL; + rest = w & ~0x7ffff000ULL; + if (a < 0 && !lui_part) continue; + if (rv64_mov_popcnt64(rest) > 4) continue; + rv64_mov_seq_zero(&p); + if (lui_part) { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, (int32_t)(lui_part >> 12), ++c); + } + if (a) { + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, a, ++c); + } + z = rest; + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + if (c) rv64_mov_best_try(&best, &p); + } + } + + { + uint32_t low12 = (uint32_t)v & 0xfff; + if (low12) { + int32_t a = rv64_mov_sext12(low12); + uint64_t w = v - (uint64_t)(int64_t)a; + if (w && w != v && rv64_mov_min_ops64(ctx, w) + 1 <= best.cost + && rv64_mov_seq64(ctx, w, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_ADDI, RV64_MOV_DST, 0, a); + } + } + + t = rv64_mov_ctz64(v); + if (v && t >= 12 && t < 64) { + uint64_t hi = v >> t; + uint64_t his = (uint64_t)(sv >> t); + if (rv64_mov_min_ops64(ctx, hi) + 1 <= best.cost + && rv64_mov_seq64(ctx, hi, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, t); + if (his != hi && rv64_mov_min_ops64(ctx, his) + 1 <= best.cost + && rv64_mov_seq64(ctx, his, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, t); + if (ctx->caps.zba && t < 32 && hi < 0x100000000ULL && (hi & 0x80000000ULL)) { + if (rv64_mov_min_ops64(ctx, (uint64_t)(int64_t)(int32_t)hi) + 1 <= best.cost + && rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)hi, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLIUW, RV64_MOV_DST, 0, t); + } + } + + if (depth < RV64_MOV_MAXDEPTH && best.cost > 2 && ctx->budget > 0 && rv64_mov_min_ops64(ctx, v) < best.cost) { + ctx->budget--; + uint32_t low12 = (uint32_t)v & 0xfff; + + { + int lz = rv64_mov_clz64(v); + for (int s = 1; s <= lz; ++s) { + uint64_t w = v << s; + int32_t sw = (int32_t)(uint32_t)w; + if ((uint64_t)(int64_t)sw != w || (w & 0xfff)) continue; + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, (int32_t)((w >> 12) & 0xfffff), 1); + rv64_mov_seq_add(&p, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, s, 2); + rv64_mov_best_try(&best, &p); + } + } + + if (sv < 0 && rv64_mov_min_ops64(ctx, ~v) + 1 <= best.cost) { + if (rv64_mov_seq64(ctx, ~v, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_XORI, RV64_MOV_DST, 0, -1); + } + + if (low12 >= 0x800) { + uint64_t w = v ^ (uint64_t)(int64_t)rv64_mov_sext12(low12); + if (w != v && rv64_mov_min_ops64(ctx, w) + 1 <= best.cost && rv64_mov_seq64(ctx, w, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_XORI, RV64_MOV_DST, 0, + rv64_mov_sext12(low12)); + } + + if (ctx->caps.zbs) { + uint64_t hi_zeros = ~v & 0xffffffff80000000ULL; + n = rv64_mov_popcnt64(hi_zeros); + if (n > 0 && n <= 3) { + uint64_t nval = v | 0xffffffff80000000ULL; + if (nval != v && rv64_mov_min_ops64(ctx, nval) + n <= best.cost && rv64_mov_seq64(ctx, nval, depth + 1, nscratch, &sub)) { + uint64_t z = hi_zeros; + rv64_mov_seq_copy(&p, &sub); + int c = sub.depth; + while (z) { + rv64_mov_seq_add(&p, RV64_MOV_BCLRI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(z), ++c); + z &= z - 1; + } + rv64_mov_best_try(&best, &p); + } + } + } + + if (ctx->caps.zba) { + static const int mk[3] = { 9, 5, 3 }; + static const uint8_t mop[3] = { RV64_MOV_SH3ADD, RV64_MOV_SH2ADD, RV64_MOV_SH1ADD }; + for (int i = 0; i < 3; ++i) { + if (v % mk[i] == 0 && rv64_mov_min_ops64(ctx, v / mk[i]) + 1 <= best.cost && rv64_mov_seq64(ctx, v / mk[i], depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, mop[i], RV64_MOV_DST, RV64_MOV_DST, 0); + } + } + + for (int sh = 12; sh < 64; ++sh) { + uint64_t mask = (UINT64_C(1) << sh) - 1; + uint64_t low = v & mask; + int64_t lo = (int64_t)low; + uint64_t w, hi, his; + if (low >> (sh - 1)) lo = (int64_t)(low - (UINT64_C(1) << sh)); + if (lo < -2048 || lo > 2047) continue; + w = v - (uint64_t)lo; + hi = w >> sh; + his = (uint64_t)((int64_t)w >> sh); + int ov = 1 + !!lo; + if (rv64_mov_min_ops64(ctx, hi) + ov <= best.cost && rv64_mov_seq64(ctx, hi, depth + 1, nscratch, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + if (his != hi && rv64_mov_min_ops64(ctx, his) + ov <= best.cost && rv64_mov_seq64(ctx, his, depth + 1, nscratch, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + if (ctx->caps.zba && sh < 32 && hi < 0x100000000ULL && (hi & 0x80000000ULL)) { + if (rv64_mov_min_ops64(ctx, (uint64_t)(int64_t)(int32_t)hi) + ov <= best.cost && rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)hi, depth + 1, nscratch, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLIUW, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + } + } + + if (nscratch && v > 0xffffffffULL) { + uint32_t lo = (uint32_t)v; + uint64_t hi = v >> 32; + + if (lo == hi) { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI2, RV64_MOV_DST, RV64_MOV_S1, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + if ((lo & 0x80000000u) && rv64_mov_seq32(ctx, ~lo & 0xffffffffu, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI2, RV64_MOV_DST, RV64_MOV_S1, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_XORI, RV64_MOV_DST, 0, 0, -1, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } else { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_t lo_seq, hi_seq; + rv64_mov_seq_copy(&lo_seq, &sub); + if (rv64_mov_seq_high(ctx, hi, 32, depth + 1, 0, &hi_seq)) { + rv64_mov_seq_rename(&lo_seq, RV64_MOV_DST, RV64_MOV_S1); + p = lo_seq; + rv64_mov_seq_concat(&p, &hi_seq); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (hi == (uint64_t)(uint32_t)(lo - 1) && (lo & 0x80000000u)) { + if (rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)lo, depth + 1, 0, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI2, RV64_MOV_DST, RV64_MOV_S1, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (!(lo & 0x80000000u)) { + uint32_t dlt = (uint32_t)hi - lo; + if (hi == (uint64_t)(uint32_t)~lo) { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_XORI2, RV64_MOV_S2, RV64_MOV_S1, 0, -1, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_S2, 0, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_S2, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (nscratch >= 2 && dlt > 0 && dlt <= 2047) { + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, RV64_MOV_ADDI2, RV64_MOV_S2, RV64_MOV_S1, 0, (int32_t)dlt, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_S2, 0, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_S2, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + if (nscratch >= 2 && ctx->caps.zba) { + static const int mk[3] = { 3, 5, 9 }; + static const uint8_t mop[3] = { RV64_MOV_SH1ADD, RV64_MOV_SH2ADD, RV64_MOV_SH3ADD }; + for (int i = 0; i < 3; ++i) { + if (hi != (uint64_t)(uint32_t)(lo * mk[i])) continue; + if (rv64_mov_seq32(ctx, lo, depth + 1, &sub)) { + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_rename(&p, RV64_MOV_DST, RV64_MOV_S1); + rv64_mov_seq_add(&p, mop[i], RV64_MOV_S2, RV64_MOV_S1, 0, 0, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_S2, 0, 0, 32, p.depth + 1); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_S2, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + } + } + + for (int sh = 33; sh <= 40; ++sh) { + uint64_t mask = (UINT64_C(1) << sh) - 1; + uint64_t lv = v & mask; + uint64_t hv = v >> sh; + if (!lv || !hv) continue; + if (!rv64_mov_seq64(ctx, lv, depth + 1, 0, &sub)) continue; + { + rv64_mov_seq_t lo_seq, hi_seq; + rv64_mov_seq_copy(&lo_seq, &sub); + if (!rv64_mov_seq_high(ctx, hv, sh, depth + 1, 0, &hi_seq)) continue; + rv64_mov_seq_rename(&lo_seq, RV64_MOV_DST, RV64_MOV_S1); + p = lo_seq; + rv64_mov_seq_concat(&p, &hi_seq); + rv64_mov_seq_add(&p, RV64_MOV_ADD, RV64_MOV_DST, RV64_MOV_DST, RV64_MOV_S1, 0, p.depth + 1); + rv64_mov_best_try(&best, &p); + } + } + } + } + + if (ctx->caps.zbb) { + uint64_t notv = ~v; + if (notv) { + int lo_z = rv64_mov_ctz64(notv); + int hi_z = rv64_mov_clz64(notv); + if (lo_z > 0 && rv64_mov_popcnt64(notv) == 64 - lo_z - hi_z) { + uint64_t rot = (v >> lo_z) | (v << (64 - lo_z)); + if (rv64_mov_seq64(ctx, rot, depth + 1, nscratch, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_RORI, RV64_MOV_DST, 0, 64 - lo_z); + } + } + } + } + + if (!best.cost) return 0; + rv64_mov_seq_copy(out, &best.seq); + return out->n; +} + +int rv64_mov_seq32(rv64_movctx_t* ctx, uint32_t v, int depth, rv64_mov_seq_t* out) +{ + rv64_movbest_t best; + best.cost = 99; + best.depth = 99; + best.seq.n = 0; + best.seq.depth = 0; + best.seq.overflow = 0; + rv64_mov_seq_t p, sub; + int t; + + if (!v || rv64_mov_fits12(v)) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, (int32_t)v, 1); + rv64_mov_best_try(&best, &p); + } + + if (ctx->caps.zbs && v && !(v & (v - 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, rv64_mov_ctz64(v), 1); + rv64_mov_best_try(&best, &p); + } + + if (v && !(v & (v + 1))) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, -1, 1); + rv64_mov_seq_add(&p, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, rv64_mov_clz64(v), 2); + rv64_mov_best_try(&best, &p); + } + + if (!(v & 0x80000000u) && !rv64_mov_fits12(v)) { + int32_t hi20 = (int32_t)(((uint64_t)v + 0x800) >> 12) & 0xfffff; + int32_t lo12 = rv64_mov_sext12(v); + rv64_mov_seq_zero(&p); + if (!lo12) { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + } else { + rv64_mov_seq_add(&p, RV64_MOV_LUI, RV64_MOV_DST, 0, 0, hi20, 1); + rv64_mov_seq_add(&p, RV64_MOV_ADDIW, RV64_MOV_DST, 0, 0, lo12, 2); + } + rv64_mov_best_try(&best, &p); + } + + if (depth < RV64_MOV_MAXDEPTH && (v & 0x80000000u) && ctx->budget > 0) { + ctx->budget--; + uint32_t w = v & 0x7fffffff; + + if (ctx->caps.zbs) { + if (!w) { + rv64_mov_seq_zero(&p); + rv64_mov_seq_add(&p, RV64_MOV_BSETI, RV64_MOV_DST, 0, 0, 31, 1); + rv64_mov_best_try(&best, &p); + } else if (rv64_mov_seq32(ctx, w, depth + 1, &sub)) { + rv64_mov_best_try1(&best, &sub, RV64_MOV_BSETI, RV64_MOV_DST, 0, 31); + } + } + if (rv64_mov_seq64(ctx, (uint64_t)(int64_t)(int32_t)v, depth + 1, 0, &sub)) { + if (ctx->caps.zba) + rv64_mov_best_try1(&best, &sub, RV64_MOV_ZEXTW, RV64_MOV_DST, 0, 0); + { + rv64_mov_seq_t q; + rv64_mov_seq_copy(&q, &sub); + rv64_mov_seq_add(&q, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, 32, sub.depth + 1); + rv64_mov_seq_add(&q, RV64_MOV_SRLI, RV64_MOV_DST, 0, 0, 32, sub.depth + 2); + rv64_mov_best_try(&best, &q); + } + } + } + + t = rv64_mov_ctz64(v); + if (depth < RV64_MOV_MAXDEPTH && v && t >= 12 && t <= 31 && ctx->budget > 0) { + ctx->budget--; + if (rv64_mov_seq32(ctx, v >> t, depth + 1, &sub)) + rv64_mov_best_try1(&best, &sub, RV64_MOV_SLLI, RV64_MOV_DST, 0, t); + } + + if (depth < RV64_MOV_MAXDEPTH && best.cost > 2 && ctx->budget > 0) { + ctx->budget--; + for (int sh = 12; sh < 32; ++sh) { + uint32_t low = v & ((UINT32_C(1) << sh) - 1); + int32_t lo; + uint32_t hi; + if (low >> (sh - 1)) + lo = (int32_t)(low - (UINT32_C(1) << sh)); + else + lo = (int32_t)low; + if (lo < -2048 || lo > 2047) continue; + hi = (v - (uint32_t)lo) >> sh; + if (!rv64_mov_seq32(ctx, hi, depth + 1, &sub)) continue; + rv64_mov_seq_copy(&p, &sub); + rv64_mov_seq_add(&p, RV64_MOV_SLLI, RV64_MOV_DST, 0, 0, sh, sub.depth + 1); + if (lo) rv64_mov_seq_add(&p, RV64_MOV_ADDI, RV64_MOV_DST, 0, 0, lo, sub.depth + 2); + rv64_mov_best_try(&best, &p); + } + } + + if (!best.cost) return 0; + rv64_mov_seq_copy(out, &best.seq); + return out->n; +} + +#define EMIT(A) emit_fn(emit_ctx, (uint32_t)(A)) + +void rv64_mov_emit_seq(int reg, int s1, int s2, const rv64_mov_seq_t* seq, rv64_mov_emit_fn emit_fn, void* emit_ctx) +{ + int vreg[3] = { reg, s1, s2 }; + uint8_t init = 0; + + for (int i = 0; i < seq->n; ++i) { + const rv64_movop_t* o = &seq->op[i]; + int rd = vreg[o->rd]; + int rs = vreg[o->rs]; + int first = !(init & (1 << o->rd)); + init |= (uint8_t)(1 << o->rd); + + switch (o->op) { + case RV64_MOV_ADDI: ADDI(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_ADDIW: ADDIW(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_LUI: LUI(rd, o->imm); break; + case RV64_MOV_SLLI: SLLI(rd, rd, o->imm); break; + case RV64_MOV_SRLI: SRLI(rd, rd, o->imm); break; + case RV64_MOV_SLLIUW: SLLIUW(rd, rd, o->imm); break; + case RV64_MOV_BSETI: BSETI_(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_BCLRI: BCLI(rd, first ? xZR : rd, o->imm); break; + case RV64_MOV_XORI: XORI(rd, rd, o->imm); break; + case RV64_MOV_ZEXTW: ZEXTW(rd, rd); break; + case RV64_MOV_RORI: RORI(rd, rd, o->imm); break; + case RV64_MOV_ADD: ADD(rd, rs, vreg[o->rs2]); break; + case RV64_MOV_SLLI2: SLLI(rd, rs, o->imm); break; + case RV64_MOV_SH1ADD: SH1ADD(rd, rs, rs); break; + case RV64_MOV_SH2ADD: SH2ADD(rd, rs, rs); break; + case RV64_MOV_SH3ADD: SH3ADD(rd, rs, rs); break; + case RV64_MOV_ADDI2: ADDI(rd, rs, o->imm); break; + case RV64_MOV_XORI2: XORI(rd, rs, o->imm); break; + default: break; + } + } +} + +#define RV64_MOV_CACHE_SIZE 1024 + +typedef struct rv64_mov_cache_s { + uint64_t v; + uint32_t key; + uint8_t n; + uint8_t used; + uint8_t pad[2]; + rv64_movop_t op[8]; +} rv64_mov_cache_t; + +static __thread rv64_mov_cache_t rv64_mov_cache[RV64_MOV_CACHE_SIZE]; + +static unsigned rv64_mov_cache_slot(uint64_t v, uint32_t key) +{ + uint64_t h = (v + ((uint64_t)key << 56)) * UINT64_C(0x9E3779B97F4A7C15); + return (unsigned)(h >> 54) & (RV64_MOV_CACHE_SIZE - 1); +} + +int rv64_mov_cache_get(uint64_t v, int nscratch, int is32, rv64_mov_seq_t* out) +{ + uint32_t key = (uint32_t)nscratch | ((uint32_t)is32 << 8); + rv64_mov_cache_t* e = &rv64_mov_cache[rv64_mov_cache_slot(v, key)]; + if (!e->used || e->v != v || e->key != key) return 0; + out->n = e->n; + out->depth = 0; + out->overflow = 0; + memcpy(out->op, e->op, (size_t)e->n * sizeof(rv64_movop_t)); + return 1; +} + +void rv64_mov_cache_put(uint64_t v, int nscratch, int is32, const rv64_mov_seq_t* seq) +{ + uint32_t key = (uint32_t)nscratch | ((uint32_t)is32 << 8); + rv64_mov_cache_t* e; + if (!seq->n || seq->n > 8) return; + e = &rv64_mov_cache[rv64_mov_cache_slot(v, key)]; + e->v = v; + e->key = key; + e->n = seq->n; + e->used = 1; + memcpy(e->op, seq->op, (size_t)seq->n * sizeof(rv64_movop_t)); +} diff --git a/src/dynarec/rv64/rv64_mov_imm.h b/src/dynarec/rv64/rv64_mov_imm.h new file mode 100644 index 000000000..6680fb139 --- /dev/null +++ b/src/dynarec/rv64/rv64_mov_imm.h @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +#ifndef __RV64_MOV_IMM_H__ +#define __RV64_MOV_IMM_H__ + +#include + +#define RV64_MOV_MAXOPS 16 +#ifndef RV64_MOV_MAXDEPTH +#define RV64_MOV_MAXDEPTH 2 +#endif +#ifndef RV64_MOV_BUDGET +#define RV64_MOV_BUDGET 4096 +#endif + +enum rv64_movop_e { + RV64_MOV_ADDI, + RV64_MOV_ADDIW, + RV64_MOV_LUI, + RV64_MOV_SLLI, + RV64_MOV_SRLI, + RV64_MOV_SLLIUW, + RV64_MOV_BSETI, + RV64_MOV_BCLRI, + RV64_MOV_XORI, + RV64_MOV_ZEXTW, + RV64_MOV_RORI, + RV64_MOV_ADD, + RV64_MOV_SLLI2, + RV64_MOV_SH1ADD, + RV64_MOV_SH2ADD, + RV64_MOV_SH3ADD, + RV64_MOV_ADDI2, + RV64_MOV_XORI2, +}; + +#define RV64_MOV_DST 0 +#define RV64_MOV_S1 1 +#define RV64_MOV_S2 2 + +typedef struct rv64_movop_s { + uint8_t op; + uint8_t rd; + uint8_t rs; + uint8_t rs2; + int32_t imm; +} rv64_movop_t; + +typedef struct rv64_mov_seq_s { + uint8_t n; + uint8_t depth; + uint8_t overflow; + rv64_movop_t op[RV64_MOV_MAXOPS]; +} rv64_mov_seq_t; + +typedef struct rv64_movcaps_s { + uint8_t zba; + uint8_t zbs; + uint8_t zbb; +} rv64_movcaps_t; + +typedef struct rv64_movctx_s { + rv64_movcaps_t caps; + int budget; +} rv64_movctx_t; + +typedef void (*rv64_mov_emit_fn)(void* ctx, uint32_t insn); + +int rv64_mov_seq64(rv64_movctx_t* ctx, uint64_t v, int depth, int nscratch, rv64_mov_seq_t* out); +int rv64_mov_seq32(rv64_movctx_t* ctx, uint32_t v, int depth, rv64_mov_seq_t* out); +void rv64_mov_emit_seq(int reg, int s1, int s2, const rv64_mov_seq_t* seq, rv64_mov_emit_fn emit_fn, void* emit_ctx); +int rv64_mov_cache_get(uint64_t v, int nscratch, int is32, rv64_mov_seq_t* out); +void rv64_mov_cache_put(uint64_t v, int nscratch, int is32, const rv64_mov_seq_t* seq); + +#endif diff --git a/src/dynarec/rv64/rv64_next.S b/src/dynarec/rv64/rv64_next.S index 3e4434cbf..5cabb705b 100644 --- a/src/dynarec/rv64/rv64_next.S +++ b/src/dynarec/rv64/rv64_next.S @@ -7,8 +7,10 @@ .align 4 .extern LinkNext +.extern LinkNextInvalid .global rv64_next +.global rv64_next_invalid // NULL pointer before rv64_next, for getDB .8byte 0 @@ -33,9 +35,7 @@ rv64_next: mv a0, Emu mv a1, RIP -#ifdef HAVE_TRACE mv a2, ra // "from" is in ra, so put in a2 -#endif addi a3, sp, 8*8 // a3 is address to change rip // call the function @@ -61,3 +61,48 @@ rv64_next: // return offset is jump address jr t3 +rv64_next_invalid: + sd RSP, (8 * 4)(Emu) + sd RIP, (8 * 17)(Emu) + + // 16 bytes aligned + addi sp, sp, -(8 * 10) + + // push regs we care that might be destoryed + sd RDI, (0*8)(sp) + sd RSI, (1*8)(sp) + sd RDX, (2*8)(sp) + sd RCX, (3*8)(sp) + sd R8, (4*8)(sp) + sd R9, (5*8)(sp) + sd RAX, (6*8)(sp) + sd RIP, (8*8)(sp) + + mv a0, Emu + mv a1, RIP + mv a2, ra // "from" is in ra, so put in a2 + addi a3, sp, 8*8 // a3 is address to change rip + + // call the function +1: + auipc t4, %pcrel_hi(LinkNextInvalid) + jalr t4, %pcrel_lo(1b) + + // reserve return value + mv t3, a0 + + // pop regs + ld RDI, (0*8)(sp) + ld RSI, (1*8)(sp) + ld RDX, (2*8)(sp) + ld RCX, (3*8)(sp) + ld R8, (4*8)(sp) + ld R9, (5*8)(sp) + ld RAX, (6*8)(sp) + ld RIP, (8*8)(sp) + + addi sp, sp, (8 * 10) + + // return offset is jump address + jr t3 + diff --git a/src/dynarec/rv64/updateflags_rv64_pass.c b/src/dynarec/rv64/updateflags_rv64_pass.c index b8ef119f8..5534f2c37 100644 --- a/src/dynarec/rv64/updateflags_rv64_pass.c +++ b/src/dynarec/rv64/updateflags_rv64_pass.c @@ -645,7 +645,7 @@ SETMARK(d_adc16); LHU(x3, xEmu, offsetof(x64emu_t, op2)); SRLI(x4, x1, 16); PUTFLAG(x4, F_CF); // CF from bit 16 of the 17 bits result - ANDI(x4, x1, 0xffff); + ZEXTH(x4, x1); SRLI(x5, x4, 15); PUTFLAG(x5, F_SF); SEQZ(x5, x4); @@ -676,7 +676,7 @@ SETMARK(d_adc16b); ADD(x1, x1, x4); // recompute res as 17 bits SRLI(x4, x1, 16); PUTFLAG(x4, F_CF); - ANDI(x4, x1, 0xffff); + ZEXTH(x4, x1); SRLI(x5, x4, 15); PUTFLAG(x5, F_SF); SEQZ(x5, x4); @@ -1023,33 +1023,37 @@ SETMARK(d_ror64); SETMARK(d_shrd16); LHU(x1, xEmu, offsetof(x64emu_t, res)); LHU(x2, xEmu, offsetof(x64emu_t, op1)); - LHU(x3, xEmu, offsetof(x64emu_t, op2)); - BNEZ(x3, 8); + LWU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + BNEZ(x6, 8); BR(xRA); // count == 0, nothing to do + SRLI(x5, x3, 16); // fill if (BOX64ENV(cputype)) { SRLI(x4, x1, 14); - SRLI(x5, x4, 1); - XOR(x4, x4, x5); + SRLI(x3, x4, 1); + XOR(x4, x4, x3); PUTFLAG(x4, F_OF2); ORI(xFlags, xFlags, 1 << F_AF); + ADDI(x4, x6, -1); + SRLW(x4, x2, x4); // CF = bit (count-1) of op1 + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, xZR); // count > 16: CF = 0 + PUTFLAG(x4, F_CF); } else { - ANDI(x4, x3, 0x0f); - ADDI(x4, x4, -16); - NEG(x4, x4); - SRL(x4, x1, x4); - SRLI(x5, x2, 15); - XOR(x4, x4, x5); + SRLI(x4, x2, 15); + XOR(x4, x5, x4); // OF = fill ^ (op1 >> 15) PUTFLAG(x4, F_OF2); ANDI(xFlags, xFlags, ~(1 << F_AF)); + ADDI(x4, x6, -1); + SRLW(x4, x2, x4); // CF = bit (count-1) of op1 + ADDI(x3, x6, -17); + SRLW(x5, x5, x3); // or bit (count-17) of fill + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, x5); + PUTFLAG(x4, F_CF); } - ADDI(x4, x3, -1); - SRLW(x4, x2, x4); // CF = bit (count-1) of op1 - if (BOX64ENV(cputype)) { - SLTI(x5, x3, 16); - BNEZ(x5, 8); - MV(x4, xZR); // count > 15: CF = 0 - } - PUTFLAG(x4, F_CF); SRLI(x4, x1, 15); PUTFLAG(x4, F_SF); SEQZ(x4, x1); @@ -1125,27 +1129,42 @@ SETMARK(d_shrd64); SETMARK(d_shld16); LHU(x1, xEmu, offsetof(x64emu_t, res)); LHU(x2, xEmu, offsetof(x64emu_t, op1)); - LHU(x3, xEmu, offsetof(x64emu_t, op2)); - BNEZ(x3, 8); + LWU(x3, xEmu, offsetof(x64emu_t, op2)); + ANDI(x6, x3, 0x1f); + BNEZ(x6, 8); BR(xRA); - ADDI(x4, x3, -16); - NEG(x4, x4); - SRLW(x4, x2, x4); // CF = bit (16-count) of op1 - PUTFLAG(x4, F_CF); + SRLI(x5, x3, 16); // fill if (BOX64ENV(cputype)) { + MOV32w(x4, 16); + SUBW(x4, x4, x6); + SRLW(x4, x2, x4); // CF = bit (16-count) of op1 + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, xZR); // count > 16: CF = 0 + PUTFLAG(x4, F_CF); SRLI(x4, x1, 15); XOR(x4, x4, xFlags); - SLTI(x5, x3, 16); - BNEZ(x5, 8); + SLTI(x3, x6, 16); + BNEZ(x3, 8); MV(x4, xFlags); // count > 15: OF = CF PUTFLAG(x4, F_OF2); ORI(xFlags, xFlags, 1 << F_AF); } else { SRLI(x4, x2, 14); - SRLI(x5, x4, 1); - XOR(x4, x4, x5); + SRLI(x3, x4, 1); + XOR(x4, x4, x3); PUTFLAG(x4, F_OF2); ANDI(xFlags, xFlags, ~(1 << F_AF)); + MOV32w(x4, 16); + SUBW(x4, x4, x6); + SRLW(x4, x2, x4); // CF = bit (16-count) of op1 + MOV32w(x3, 32); + SUBW(x3, x3, x6); + SRLW(x5, x5, x3); // or bit (32-count) of fill + SLTI(x3, x6, 17); + BNEZ(x3, 8); + MV(x4, x5); + PUTFLAG(x4, F_CF); } SRLI(x4, x1, 15); PUTFLAG(x4, F_SF); diff --git a/src/elfs/elfhacks.c b/src/elfs/elfhacks.c index a7509023c..1817408bd 100644 --- a/src/elfs/elfhacks.c +++ b/src/elfs/elfhacks.c @@ -7,7 +7,6 @@ */ #ifndef _GNU_SOURCE -#define _GNU_SOURCE #endif #include diff --git a/src/elfs/elfhash.c b/src/elfs/elfhash.c index 71b817feb..e4fb7dc94 100644 --- a/src/elfs/elfhash.c +++ b/src/elfs/elfhash.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/elfs/elfhash32.c b/src/elfs/elfhash32.c index d742d874c..f27bc7145 100644 --- a/src/elfs/elfhash32.c +++ b/src/elfs/elfhash32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 0217e9c43..255e06c21 100644 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -433,7 +432,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) setProtection_elf((uintptr_t)p, asize, prot); head->multiblocks[n].p = p; if (file_read_size) { - fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET); + fseeko(head->file, head->multiblocks[n].offs, SEEK_SET); if(fread((void*)head->multiblocks[n].paddr, file_read_size, 1, head->file)!=1) { printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, (box64_pagesize - 1), head->name); return 1; @@ -458,7 +457,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin) char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase); printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); if(e->p_filesz) { - fseeko64(head->file, e->p_offset, SEEK_SET); + fseeko(head->file, e->p_offset, SEEK_SET); if(fread(dest, e->p_filesz, 1, head->file)!=1) { mutex_unlock(&context->mutex_tls); printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz); @@ -1138,6 +1137,81 @@ page description of the -r option). For more details of this token expansion, se uname(1) man page description of the -i option). For more details of this token expansion, see “System Specific Shared Objects” */ +char* ExpandNeededLibs(elfheader_t* h, char* rpath) +{ + if(!rpath || !h) return rpath; + char* rpathref = rpath; + while(strstr(rpath, "$$ORIGIN")) { + char* origin = box_strdup(h->path); + char* p = strrchr(origin, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$$ORIGIN")+strlen(origin)+1); + p = strstr(rpath, "$$ORIGIN"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, origin); + strcat(tmp, p+strlen("$$ORIGIN")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(origin); + } + while(strstr(rpath, "$ORIGIN")) { + char* origin = box_strdup(h->path); + char* p = strrchr(origin, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1); + p = strstr(rpath, "$ORIGIN"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, origin); + strcat(tmp, p+strlen("$ORIGIN")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(origin); + } + while(strstr(rpath, "${ORIGIN}")) { + char* origin = box_strdup(h->path); + char* p = strrchr(origin, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1); + p = strstr(rpath, "${ORIGIN}"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, origin); + strcat(tmp, p+strlen("${ORIGIN}")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(origin); + if(!FileExist(rpath, 0) && strstr(rpath, "/../../")) { + tmp = (char*)box_calloc(1, strlen(rpath)+1); + strcpy(tmp, rpath); + // check if one "/.." could be removed for the folder to exist + char* p = strstr(tmp, "/../../"); + memmove(p, p+3, strlen(p+3)+1); + if(FileExist(tmp, 0)) { + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + } else + box_free(tmp); + } + } + while(strstr(rpath, "${PLATFORM}")) { + char* platform = box_strdup("x86_64"); + char* p = strrchr(platform, '/'); + if(p) *p = '\0'; // remove file name to have only full path, without last '/' + char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1); + p = strstr(rpath, "${PLATFORM}"); + memcpy(tmp, rpath, p-rpath); + strcat(tmp, platform); + strcat(tmp, p+strlen("${PLATFORM}")); + if(rpath!=rpathref) + box_free(rpath); + rpath = tmp; + box_free(platform); + } + return rpath; +} int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu) { if(h->needed) // already done @@ -1150,75 +1224,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de if(tag==DT_RPATH || tag==DT_RUNPATH) { char *rpathref = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); char* rpath = rpathref; - while(strstr(rpath, "$$ORIGIN")) { - char* origin = box_strdup(h->path); - char* p = strrchr(origin, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$$ORIGIN")+strlen(origin)+1); - p = strstr(rpath, "$$ORIGIN"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, origin); - strcat(tmp, p+strlen("$$ORIGIN")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(origin); - } - while(strstr(rpath, "$ORIGIN")) { - char* origin = box_strdup(h->path); - char* p = strrchr(origin, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1); - p = strstr(rpath, "$ORIGIN"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, origin); - strcat(tmp, p+strlen("$ORIGIN")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(origin); - } - while(strstr(rpath, "${ORIGIN}")) { - char* origin = box_strdup(h->path); - char* p = strrchr(origin, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1); - p = strstr(rpath, "${ORIGIN}"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, origin); - strcat(tmp, p+strlen("${ORIGIN}")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(origin); - if(!FileExist(rpath, 0) && strstr(rpath, "/../../")) { - tmp = (char*)box_calloc(1, strlen(rpath)+1); - strcpy(tmp, rpath); - // check if one "/.." could be removed for the folder to exist - char* p = strstr(tmp, "/../../"); - memmove(p, p+3, strlen(p+3)+1); - if(FileExist(tmp, 0)) { - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - } else - box_free(tmp); - } - } - while(strstr(rpath, "${PLATFORM}")) { - char* platform = box_strdup("x86_64"); - char* p = strrchr(platform, '/'); - if(p) *p = '\0'; // remove file name to have only full path, without last '/' - char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1); - p = strstr(rpath, "${PLATFORM}"); - memcpy(tmp, rpath, p-rpath); - strcat(tmp, platform); - strcat(tmp, p+strlen("${PLATFORM}")); - if(rpath!=rpathref) - box_free(rpath); - rpath = tmp; - box_free(platform); - } + rpath = ExpandNeededLibs(h, rpath); if(strchr(rpath, '$')) { printf_log(LOG_INFO, "Warning, RPATH with $ variable not supported yet (%s)\n", rpath); } else { @@ -1255,8 +1261,13 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de my_context->neededlibs = h->needed; int j=0; for (size_t i=0; inumDynamic; ++i) - if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED) - h->needed->names[j++] = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); + if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED) { + char* path = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val); + char* newpath = ExpandNeededLibs(h, path); + if(path!=newpath) + path = add1nsname(h->needed, newpath); + h->needed->names[j++] = path; + } #ifndef ANDROID if(box64_is32bits && strstr(h->name, "lsteamclient.dll.so")) h->needed->names[j++] = "libgcc_s.so.1"; @@ -1937,9 +1948,11 @@ void CreateMemorymapFile(box64context_t* context, int fd) elfheader_t* h = FindElfAddress(my_context, start); int l = strlen(line); if(h && l<73) { + line[strcspn(line, "\n")] = '\0'; sprintf(buff, "%s%*s\n", line, 74-l, h->name); dummy = write(fd, buff, strlen(buff)); } else if(start==(uintptr_t)my_context->stack) { + line[strcspn(line, "\n")] = '\0'; sprintf(buff, "%s%*s\n", line, 74-l, "[stack]"); dummy = write(fd, buff, strlen(buff)); } else if (strstr(line, "[stack]")) { diff --git a/src/elfs/elfloader32.c b/src/elfs/elfloader32.c index 766393884..f5798e23e 100644 --- a/src/elfs/elfloader32.c +++ b/src/elfs/elfloader32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -156,14 +155,14 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin void* image = NULL; if(!head->vaddr) { sz += head->align; - raw = mmap64(from_ptrv(offs), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + raw = mmap(from_ptrv(offs), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); image = (void*)(((uintptr_t)raw+max_align)&~max_align); } else { if(from_ptr(head->vaddr)&(box64_pagesize-1)) { // load address is not page-aligned, round down and increase size uintptr_t aligned_addr = ALIGN_DOWN(from_ptr(head->vaddr)); size_t extra = from_ptr(head->vaddr) - aligned_addr; - raw = mmap64((void*)aligned_addr, sz + extra, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + raw = mmap((void*)aligned_addr, sz + extra, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); if(raw != MAP_FAILED && (uintptr_t)raw == aligned_addr) { image = from_ptrv(head->vaddr); sz += extra; @@ -171,7 +170,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin image = raw; } } else { - image = raw = mmap64(from_ptrv(head->vaddr), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + image = raw = mmap(from_ptrv(head->vaddr), sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); } } if(image!=MAP_FAILED && !head->vaddr && image!=from_ptrv(offs)) { @@ -231,7 +230,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin try_mmap = 0; if(try_mmap) { printf_dump(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name); - void* p = mmap64( + void* p = mmap( (void*)head->multiblocks[n].paddr, head->multiblocks[n].size, prot, @@ -269,7 +268,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin file_map_addr += box64_pagesize; if(file_map_addr < head->multiblocks[n].paddr + e->p_filesz) { size_t file_map_delta = file_map_addr - paddr; - void* file_map = mmap64((void*)file_map_addr, file_size - file_map_delta, prot | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, head->fileno, file_offset + file_map_delta); + void* file_map = mmap((void*)file_map_addr, file_size - file_map_delta, prot | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, head->fileno, file_offset + file_map_delta); mapped_file = file_map == (void*)file_map_addr; if(mapped_file) { p = (void*)paddr; @@ -283,7 +282,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin } if (!mapped_file && !file_delta) { printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); - p = mmap64((void*)paddr, asize, prot | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + p = mmap((void*)paddr, asize, prot | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); } else if (!mapped_file) { // difference in pagesize, so need to mmap only what needed to be... //check startint point @@ -299,7 +298,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin } if(new_size>0) { printf_dump(log_level, "Allocating 0x%zx (0x%zx/0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", ALIGN(new_size), paddr, e->p_memsz, (void*)new_addr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name); - p = mmap64( + p = mmap( (void*)new_addr, ALIGN(new_size), prot|PROT_WRITE, @@ -326,7 +325,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin setProtection_elf((uintptr_t)p, asize, prot); head->multiblocks[n].p = p; if (file_read_size) { - fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET); + fseeko(head->file, head->multiblocks[n].offs, SEEK_SET); if(fread((void*)head->multiblocks[n].paddr, file_read_size, 1, head->file)!=1) { printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, (box64_pagesize - 1), head->name); return 1; @@ -351,7 +350,7 @@ int AllocLoadElfMemory32(box64context_t* context, elfheader_t* head, int mainbin char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase); printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz); if(e->p_filesz) { - fseeko64(head->file, e->p_offset, SEEK_SET); + fseeko(head->file, e->p_offset, SEEK_SET); if(fread(dest, e->p_filesz, 1, head->file)!=1) { mutex_unlock(&context->mutex_tls); printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz); diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index 2d63cf4d4..116672283 100644 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -28,7 +27,7 @@ static int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t printf_log(LOG_INFO, "Section Header \"%s\" (off=%ld, size=%ld) has size (not multiple of %ld)\n", name, s->sh_offset, s->sh_size, sizeof(Elf64_Sym)); } *SH = box_calloc(1, s->sh_size); - fseeko64(f, s->sh_offset ,SEEK_SET); + fseeko(f, s->sh_offset ,SEEK_SET); if(fread(*SH, s->sh_size, 1, f)!=1) { printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%ld, size=%ld)\n", name, s->sh_offset, s->sh_size); return -1; @@ -71,7 +70,7 @@ static void LoadProgramSection(FILE *f, elfheader_t* h, int size, uint32_t type, for (size_t i=0; inumPHEntries && !*what; ++i) { if(h->PHEntries._64[i].p_type == type) { *what = box_calloc(1, h->PHEntries._64[i].p_memsz); - fseeko64(f, h->PHEntries._64[i].p_offset ,SEEK_SET); + fseeko(f, h->PHEntries._64[i].p_offset ,SEEK_SET); if(fread(h->Dynamic._64, h->PHEntries._64[i].p_filesz, 1, f)!=1) { printf_log(LOG_INFO, "Cannot read Program Header %zd \"%s\" (off=%ld, size=%ld)\n", i, "PT_DYNAMIC", h->PHEntries._64[i].p_offset, h->PHEntries._64[i].p_filesz); box_free(*what); @@ -104,7 +103,7 @@ static void* LoadSubLoadSection(FILE *f, elfheader_t* h, uintptr_t offset, size_ size = end - start; } ret = box_calloc(1, size); - fseeko64(f, h->PHEntries._64[i].p_offset + offset - h->PHEntries._64[i].p_vaddr, SEEK_SET); + fseeko(f, h->PHEntries._64[i].p_offset + offset - h->PHEntries._64[i].p_vaddr, SEEK_SET); size_t to_read = size; if (size + offset - h->PHEntries._64[i].p_vaddr > h->PHEntries._64[i].p_filesz) to_read -= (size + offset - h->PHEntries._64[i].p_vaddr) - h->PHEntries._64[i].p_filesz; @@ -197,7 +196,7 @@ elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec) if(header.e_shentsize && !h->numSHEntries && header.e_shoff) { printf_dump(LOG_DEBUG, "Read number of Sections in 1st Section\n"); // read 1st section header and grab actual number from here - fseeko64(f, header.e_shoff, SEEK_SET); + fseeko(f, header.e_shoff, SEEK_SET); Elf64_Shdr section; if(fread(§ion, sizeof(Elf64_Shdr), 1, f)!=1) { box_free(h); @@ -210,7 +209,7 @@ elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec) // now read all section headers printf_dump(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries); h->SHEntries._64 = (Elf64_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf64_Shdr)); - fseeko64(f, header.e_shoff ,SEEK_SET); + fseeko(f, header.e_shoff ,SEEK_SET); if(fread(h->SHEntries._64, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Section Header\n"); @@ -226,7 +225,7 @@ elfheader_t* ParseElfHeader64(FILE* f, const char* name, int exec) printf_dump(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries); h->PHEntries._64 = (Elf64_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf64_Phdr)); - fseeko64(f, header.e_phoff ,SEEK_SET); + fseeko(f, header.e_phoff ,SEEK_SET); if(fread(h->PHEntries._64, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Program Header\n"); diff --git a/src/elfs/elfparser32.c b/src/elfs/elfparser32.c index a7901f960..b11d42acb 100755 --- a/src/elfs/elfparser32.c +++ b/src/elfs/elfparser32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -26,7 +25,7 @@ static int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %ld)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym)); } *SH = actual_calloc(1, s->sh_size); - fseeko64(f, s->sh_offset ,SEEK_SET); + fseeko(f, s->sh_offset ,SEEK_SET); if(fread(*SH, s->sh_size, 1, f)!=1) { printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size); return -1; @@ -128,7 +127,7 @@ elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) if(h->numSHEntries == 0) { printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n"); // read 1st section header and grab actual number from here - fseeko64(f, header.e_shoff, SEEK_SET); + fseeko(f, header.e_shoff, SEEK_SET); Elf32_Shdr section; if(fread(§ion, sizeof(Elf32_Shdr), 1, f)!=1) { actual_free(h); @@ -140,7 +139,7 @@ elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) // now read all section headers printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries); h->SHEntries._32 = (Elf32_Shdr*)actual_calloc(h->numSHEntries, sizeof(Elf32_Shdr)); - fseeko64(f, header.e_shoff ,SEEK_SET); + fseeko(f, header.e_shoff ,SEEK_SET); if(fread(h->SHEntries._32, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Section Header\n"); @@ -156,7 +155,7 @@ elfheader_t* ParseElfHeader32(FILE* f, const char* name, int exec) printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries); h->PHEntries._32 = (Elf32_Phdr*)actual_calloc(h->numPHEntries, sizeof(Elf32_Phdr)); - fseeko64(f, header.e_phoff ,SEEK_SET); + fseeko(f, header.e_phoff ,SEEK_SET); if(fread(h->PHEntries._32, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) { FreeElfHeader(&h); printf_log(LOG_INFO, "Cannot read all Program Header\n"); diff --git a/src/emu/modrm.h b/src/emu/modrm.h index b46576428..7bc144c91 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT #include #define F8 *(uint8_t*)(addr++) @@ -25,6 +25,8 @@ #ifdef TEST_INTERPRETER #define GETED(D) oped=TestEd(test, &addr, rex, nextop, D) +#define GETE1(D) oped=TestEd1(test, &addr, rex, nextop, D) +#define GETE2(D) oped=TestEd2(test, &addr, rex, nextop, D) #define GETE4(D) oped=TestEd4(test, &addr, rex, nextop, D) #define GETE8(D) oped=TestEd8(test, &addr, rex, nextop, D) #define GETET(D) oped=TestEdt(test, &addr, rex, nextop, D) @@ -35,6 +37,7 @@ #define GETEW(D) oped=TestEw(test, &addr, rex, nextop, D) #define GETGW opgd=GetGw(test->emu, &addr, rex, nextop) #define GETEX(D) opex=TestEx(test, &addr, rex, nextop, D, 16) +#define GETEX2(D) opex=TestEx(test, &addr, rex, nextop, D, 2) #define GETEX4(D) opex=TestEx(test, &addr, rex, nextop, D, 4) #define GETEX8(D) opex=TestEx(test, &addr, rex, nextop, D, 8) #define GETGX opgx=GetGx(test->emu, &addr, rex, nextop) @@ -47,6 +50,8 @@ #define GETVD opvd=&test->emu->regs[vex.v] #else #define GETED(D) oped=GetEd(emu, &addr, rex, nextop, D) +#define GETE1(D) GETED(D) +#define GETE2(D) GETED(D) #define GETE4(D) GETED(D) #define GETE8(D) GETED(D) #define GETET(D) GETED(D) @@ -57,6 +62,7 @@ #define GETEW(D) oped=GetEw(emu, &addr, rex, nextop, D) #define GETGW opgd=GetGw(emu, &addr, rex, nextop) #define GETEX(D) opex=GetEx(emu, &addr, rex, nextop, D) +#define GETEX2(D) GETEX(D) #define GETEX4(D) GETEX(D) #define GETEX8(D) GETEX(D) #define GETGX opgx=GetGx(emu, &addr, rex, nextop) diff --git a/src/emu/x64compstrings.c b/src/emu/x64compstrings.c index 666196cff..b9642d922 100644 --- a/src/emu/x64compstrings.c +++ b/src/emu/x64compstrings.c @@ -134,3 +134,9 @@ uint32_t sse42_compare_string_implicit_len(x64emu_t* emu, sse_regs_t* mem, sse_r } return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8, 0); } + +// for the dynarec: REX.W is passed in bit 8 of imm8_w, to spare a register +uint32_t sse42_compare_string_explicit_len_imm8w(x64emu_t* emu, sse_regs_t* mem, int64_t lmem, sse_regs_t* reg, int64_t lreg, uint32_t imm8_w) +{ + return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8_w & 0xff, (imm8_w >> 8) & 1); +} diff --git a/src/emu/x64compstrings.h b/src/emu/x64compstrings.h index 0cf5dad5d..cd29311ca 100644 --- a/src/emu/x64compstrings.h +++ b/src/emu/x64compstrings.h @@ -10,5 +10,6 @@ typedef struct x64emu_s x64emu_t; uint32_t sse42_compare_string_explicit_len(x64emu_t* emu, sse_regs_t* a, int64_t la, sse_regs_t* b, int64_t lb, uint8_t imm8, int w); uint32_t sse42_compare_string_implicit_len(x64emu_t* emu, sse_regs_t* a, sse_regs_t* b, uint8_t imm8); +uint32_t sse42_compare_string_explicit_len_imm8w(x64emu_t* emu, sse_regs_t* a, int64_t la, sse_regs_t* b, int64_t lb, uint32_t imm8_w); #endif //__X64_CMPSTRINGS_H__ \ No newline at end of file diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index 16c321776..1edfe49c6 100644 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -1235,23 +1235,27 @@ void UpdateFlags(x64emu_t* emu) case d_shrd16: cnt = emu->op2.u16; if (cnt > 0) { - cc = emu->op1.u16 & (1 << (cnt - 1)); - if (cnt > 15 && BOX64ENV(cputype)) + // fill operand is stored in the upper half of op2 + if (cnt > 16) + cc = (emu->op2.u64 >> 16) & 0xffff & (1u << (cnt - 17)); + else + cc = emu->op1.u16 & (1 << (cnt - 1)); + if (cnt > 16 && BOX64ENV(cputype)) cc = 0; CONDITIONAL_SET_FLAG(cc, F_CF); CONDITIONAL_SET_FLAG(!emu->res.u16, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); + if BOX64ENV (cputype) { + CONDITIONAL_SET_FLAG(XOR2(emu->res.u16 >> 14), F_OF); + } else { + CONDITIONAL_SET_FLAG((((emu->op2.u64 >> 16) & 0xffff) ^ (emu->op1.u16 >> 15)) & 1, F_OF); + } + if (BOX64ENV(cputype)) + SET_FLAG(F_AF); + else + CLEAR_FLAG(F_AF); } - if BOX64ENV (cputype) { - CONDITIONAL_SET_FLAG(XOR2(emu->res.u16 >> 14), F_OF); - } else { - CONDITIONAL_SET_FLAG(((emu->res.u16 >> (16 - (cnt & 15))) ^ (emu->op1.u16 >> 15)) & 1, F_OF); - } - if (BOX64ENV(cputype)) - SET_FLAG(F_AF); - else - CLEAR_FLAG(F_AF); break; case d_shrd32: cnt = emu->op2.u32; @@ -1294,7 +1298,12 @@ void UpdateFlags(x64emu_t* emu) case d_shld16: cnt = emu->op2.u16; if (cnt > 0) { - cc = emu->op1.u16 & (1 << (16 - cnt)); + if (cnt > 16) + cc = (emu->op2.u64 >> 16) & 0xffff & (1u << (32 - cnt)); + else + cc = emu->op1.u16 & (1 << (16 - cnt)); + if (cnt > 16 && BOX64ENV(cputype)) + cc = 0; CONDITIONAL_SET_FLAG(cc, F_CF); CONDITIONAL_SET_FLAG(!emu->res.u16, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c index c72aa714d..922800471 100644 --- a/src/emu/x64int3.c +++ b/src/emu/x64int3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/emu/x64printer.c b/src/emu/x64printer.c index 7654cb67d..131a6d746 100644 --- a/src/emu/x64printer.c +++ b/src/emu/x64printer.c @@ -7214,6 +7214,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } else if (w == pFpppiiiiiii) { snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); + } else if (w == pFpppppiiiii) { + snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } else if (w == pFpppppppppp) { snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } else if (w == vFEppLpLpLLpp) { diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 17502ed7f..6d18e0138 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -947,8 +946,6 @@ int Run(x64emu_t *emu, int step) if(is32bits) { uint32_t new_addr = (rex.is32bits && rex.is66)?(F16):(F32); uint16_t new_cs = F16; - Push32(emu, emu->segs[_CS]); - Push32(emu, addr); #ifndef TEST_INTERPRETER if((new_cs&3)!=3) { // R_RIP doesn't advance @@ -957,6 +954,8 @@ int Run(x64emu_t *emu, int step) EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level goto fini; } + Push32(emu, emu->segs[_CS]); + Push32(emu, addr); emu->segs[_CS] = new_cs; addr = new_addr; if(is32bits!=(emu->segs[_CS]==0x23)) { @@ -1665,32 +1664,44 @@ int Run(x64emu_t *emu, int step) tmp16u = F16; if(rex.is32bits || !rex.w) { addr = Pop32(emu); - emu->segs[_CS] = Pop32(emu); // no check, no use.... + tmp16u = Pop32(emu); // no check, no use.... } else { addr = Pop64(emu); - emu->segs[_CS] = Pop64(emu); // no check, no use.... + tmp16u = Pop64(emu); // no check, no use.... } R_RSP += tmp16u; - is32bits = (R_CS==0x23); // checking if CS changed + is32bits = (tmp16u==0x23); // checking if CS changed #ifndef TEST_INTERPRETER if(is32bits) running32bits = 1; #endif + if((tmp16u&3)!=3) { + R_RSP-=(rex.w?4:8)*2; + EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level + goto fini; + } else + emu->segs[_CS] = tmp16u; STEP2; break; case 0xCB: /* FAR RET */ if(rex.is32bits || !rex.w) { addr = Pop32(emu); - emu->segs[_CS] = Pop32(emu); // no check.... + tmp16u = Pop32(emu); // no check.... } else { addr = Pop64(emu); - emu->segs[_CS] = Pop64(emu); // no check.... + tmp16u = Pop64(emu); // no check.... } - is32bits = (R_CS==0x23); // checking if CS changed + is32bits = (tmp16u==0x23); // checking if CS changed #ifndef TEST_INTERPRETER if(is32bits) running32bits = 1; #endif + if((tmp16u&3)!=3) { + R_RSP-=(rex.w?4:8)*2; + EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level + goto fini; + } else + emu->segs[_CS] = tmp16u; STEP2; break; case 0xCC: /* INT 3 */ @@ -2408,6 +2419,18 @@ int Run(x64emu_t *emu, int step) EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0); goto fini; } else { + tmp8u = 0; + if(rex.is32bits || !rex.w) { + if((ED->word[2]&3)!=3) + tmp8u = 1; + } else { + if(((ED+1)->word[0]&3)!=3) + tmp8u = 2; + } + if(tmp8u) { + EmitSignal(emu, X64_SIGSEGV, (void*)R_RIP, 0xbad0); // GP if trying to change priv level + goto fini; + } if(rex.is32bits || !rex.w) { Push32(emu, R_CS); Push32(emu, addr); diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index 23a97dee2..1eb668e97 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -271,7 +270,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) if(MODREG) { EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0); } else { - GETEX(0); + GETEX8(0); GETGX; EX->q[0] = GX->q[0]; } @@ -295,7 +294,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0x16: /* MOVHPS Gx,Ex */ nextop = F8; /* MOVLHPS Gx,Ex (Ex==reg) */ - GETEX(0); + GETEX8(0); GETGX; GX->q[1] = EX->q[0]; break; @@ -304,7 +303,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) if(MODREG) { EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0); } else { - GETEX(0); + GETEX8(0); GETGX; EX->q[0] = GX->q[1]; } @@ -385,17 +384,17 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0x2C: /* CVTTPS2PI Gm, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGM; tmp64s = EX->f[1]; - if (tmp64s==(int32_t)tmp64s && !isnanf(EX->f[1])) + if (tmp64s==(int32_t)tmp64s && !isnan(EX->f[1])) GM->sd[1] = (int32_t)tmp64s; else { mxcsr_raise_invalid(emu); GM->sd[1] = INT32_MIN; } tmp64s = EX->f[0]; - if (tmp64s==(int32_t)tmp64s && !isnanf(EX->f[0])) + if (tmp64s==(int32_t)tmp64s && !isnan(EX->f[0])) GM->sd[0] = (int32_t)tmp64s; else { mxcsr_raise_invalid(emu); @@ -405,10 +404,10 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) case 0x2D: /* CVTPS2PI Gm, Ex */ // rounding should be done; and indefinite integer should also be assigned if overflow or NaN/Inf nextop = F8; - GETEX(0); + GETEX8(0); GETGM; for(int i=1; i>=0; --i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -442,9 +441,9 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) case 0x2F: /* COMISS Gx, Ex */ RESET_FLAGS(emu); nextop = F8; - GETEX(0); + GETEX4(0); GETGX; - if(isnanf(GX->f[0]) || isnanf(EX->f[0])) { + if(isnan(GX->f[0]) || isnan(EX->f[0])) { SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF); } else if(isgreater(GX->f[0], EX->f[0])) { CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF); @@ -855,13 +854,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] += EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); @@ -873,13 +872,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] *= EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); @@ -887,11 +886,11 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0x5A: /* CVTPS2PD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; #ifdef RV64 for(int i=1; i>=0; --i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->q[i] = ((uint64_t)(EX->ud[i] & 0x80000000) << 32) | ((uint64_t)(EX->ud[i] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -921,13 +920,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] -= EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); @@ -948,13 +947,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) { + if(isnan(GX->f[i])) { GX->ud[i] |= 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] /= EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); @@ -1839,7 +1838,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) break; case 0xC4: /* PINSRW Gm,Ew,Ib */ nextop = F8; - GETED(1); + GETE2(1); GETGM; tmp8u = F8; GM->uw[tmp8u&3] = ED->word[0]; // only low 16bits diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c index 25b94d21e..5018fd0e4 100644 --- a/src/emu/x64run66.c +++ b/src/emu/x64run66.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 7da72c75a..cfee100af 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -1,5 +1,4 @@ -// SPDX-License-Identifier: MIT -#define _GNU_SOURCE +// SPDX-License-Identifier: MIT #include #include #include @@ -28,7 +27,7 @@ #include "modrm.h" #include "x64compstrings.h" -#include "random.h" +#include "random.h" static uint8_t ff_mult(uint8_t a, uint8_t b) { @@ -285,7 +284,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0x2F: /* COMISD Gx, Ex */ RESET_FLAGS(emu); nextop = F8; - GETEX(0); + GETEX8(0); GETGX; if(isnan(GX->d[0]) || isnan(EX->d[0])) { SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF); @@ -520,35 +519,35 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 0x21: /* PMOVSXBD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=3; i>=0; --i) GX->sd[i] = EX->sb[i]; break; case 0x22: /* PMOVSXBQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX2(0); GETGX; for(int i=1; i>=0; --i) GX->sq[i] = EX->sb[i]; break; case 0x23: /* PMOVSXWD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=3; i>=0; --i) GX->sd[i] = EX->sw[i]; break; case 0x24: /* PMOVSXWQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=1; i>=0; --i) GX->sq[i] = EX->sw[i]; break; case 0x25: /* PMOVSXDQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=1; i>=0; --i) GX->sq[i] = EX->sd[i]; @@ -599,35 +598,35 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 0x31: /* PMOVZXBD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=3; i>=0; --i) GX->ud[i] = EX->ub[i]; break; case 0x32: /* PMOVZXBQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX2(0); GETGX; for(int i=1; i>=0; --i) GX->q[i] = EX->ub[i]; break; case 0x33: /* PMOVZXWD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=3; i>=0; --i) GX->ud[i] = EX->uw[i]; break; case 0x34: /* PMOVZXWQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; for(int i=1; i>=0; --i) GX->q[i] = EX->uw[i]; break; case 0x35: /* PMOVZXDQ Gx, Ex */ nextop = F8; - GETEX(0); + GETEX8(0); GETGX; for(int i=1; i>=0; --i) GX->q[i] = EX->ud[i]; @@ -897,45 +896,45 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp8u &= 3; switch(tmp8u) { case ROUND_Nearest: { - int round = fegetround(); - fesetround(FE_TONEAREST); - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = nearbyintf(EX->f[i]); - fesetround(round); - break; - } - case ROUND_Down: - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = floorf(EX->f[i]); - break; - case ROUND_Up: - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = ceilf(EX->f[i]); - break; - case ROUND_Chop: - for(int i=0; i<4; ++i) - #ifdef RV64 - if(isnanf(EX->f[i])) - GX->ud[i] = EX->ud[i] | 0x00400000; - else - #endif - GX->f[i] = truncf(EX->f[i]); - break; + int round = fegetround(); + fesetround(FE_TONEAREST); + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnan(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = nearbyintf(EX->f[i]); + fesetround(round); + break; + } + case ROUND_Down: + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnan(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = floorf(EX->f[i]); + break; + case ROUND_Up: + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnan(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = ceilf(EX->f[i]); + break; + case ROUND_Chop: + for(int i=0; i<4; ++i) + #ifdef RV64 + if(isnan(EX->f[i])) + GX->ud[i] = EX->ud[i] | 0x00400000; + else + #endif + GX->f[i] = truncf(EX->f[i]); + break; } break; case 0x09: // ROUNDPD Gx, Ex, u8 @@ -948,46 +947,46 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) else tmp8u &= 3; switch(tmp8u) { - case ROUND_Nearest: { - int round = fegetround(); - fesetround(FE_TONEAREST); - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = nearbyint(EX->d[i]); - fesetround(round); - break; - } - case ROUND_Down: - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = floor(EX->d[i]); - break; - case ROUND_Up: - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = ceil(EX->d[i]); - break; - case ROUND_Chop: - for(int i=0; i<2; ++i) - #ifdef RV64 - if(isnan(EX->d[i])) - GX->q[i] = EX->q[i] | 0x0008000000000000ULL; - else - #endif - GX->d[i] = trunc(EX->d[i]); - break; + case ROUND_Nearest: { + int round = fegetround(); + fesetround(FE_TONEAREST); + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = nearbyint(EX->d[i]); + fesetround(round); + break; + } + case ROUND_Down: + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = floor(EX->d[i]); + break; + case ROUND_Up: + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = ceil(EX->d[i]); + break; + case ROUND_Chop: + for(int i=0; i<2; ++i) + #ifdef RV64 + if(isnan(EX->d[i])) + GX->q[i] = EX->q[i] | 0x0008000000000000ULL; + else + #endif + GX->d[i] = trunc(EX->d[i]); + break; } break; case 0x0A: // ROUNDSS Gx, Ex, u8 @@ -996,7 +995,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GETGX; tmp8u = F8; // ignoring bit 3 interupt thingy #ifdef RV64 - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[0] = EX->ud[0] | 0x00400000; break; } @@ -1024,18 +1023,18 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) break; } break; - case 0x0B: // ROUNDSD Gx, Ex, u8 - nextop = F8; - GETEX(1); - GETGX; - tmp8u = F8; // ignoring bit 3 interupt thingy - #ifdef RV64 - if(isnan(EX->d[0])) { - GX->q[0] = EX->q[0] | 0x0008000000000000ULL; - break; - } - #endif - if(tmp8u&4) + case 0x0B: // ROUNDSD Gx, Ex, u8 + nextop = F8; + GETEX(1); + GETGX; + tmp8u = F8; // ignoring bit 3 interupt thingy + #ifdef RV64 + if(isnan(EX->d[0])) { + GX->q[0] = EX->q[0] | 0x0008000000000000ULL; + break; + } + #endif + if(tmp8u&4) tmp8u = emu->mxcsr.f.MXCSR_RC; else tmp8u &= 3; @@ -1150,7 +1149,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0x20: // PINSRB GX, ED, u8 nextop = F8; - GETED(1); // It's ED, and not EB + GETE1(1); GETGX; tmp8u = F8; GX->ub[tmp8u&0xf] = ED->byte[0]; @@ -1177,11 +1176,11 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GX->ud[tmp8u&0x3] = ED->dword[0]; break; - case 0x40: { /* DPPS Gx, Ex, Ib */ + case 0x40: { /* DPPS Gx, Ex, Ib */ nextop = F8; GETEX(1); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); tmp8u = F8; tmpf = 0.0f; for(int i=0; i<4; ++i) @@ -1189,14 +1188,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmpf += GX->f[i]*EX->f[i]; for(int i=0; i<4; ++i) GX->f[i] = (tmp8u&(1<d[1]*EX->d[1]; GX->d[0] = (tmp8u&(1<<(0)))?tmpd:0.0; GX->d[1] = (tmp8u&(1<<(1)))?tmpd:0.0; - fesetround(oldround); - } - break; + fesetround(oldround); + } + break; case 0x42: /* MPSADBW Gx, Ex, Ib */ nextop = F8; GETEX(1); @@ -1435,34 +1434,34 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) fesetround(oldround); } break; - case 0x5A: { /* CVTPD2PS Gx, Ex */ - nextop = F8; - GETEX(0); - GETGX; - int oldround = mxcsr_setround(emu); - #ifdef RV64 - for (int i = 0; i < 2; ++i) { - if (isnan(EX->d[i])) - GX->ud[i] = ((EX->q[i] >> 32) & 0x80000000) - | ((EX->q[i] >> 29) & 0x007fffff) - | 0x7fc00000; - else - GX->f[i] = EX->d[i]; - } - #else - GX->f[0] = EX->d[0]; - GX->f[1] = EX->d[1]; - #endif - GX->q[1] = 0; - fesetround(oldround); - } - break; + case 0x5A: { /* CVTPD2PS Gx, Ex */ + nextop = F8; + GETEX(0); + GETGX; + int oldround = mxcsr_setround(emu); + #ifdef RV64 + for (int i = 0; i < 2; ++i) { + if (isnan(EX->d[i])) + GX->ud[i] = ((EX->q[i] >> 32) & 0x80000000) + | ((EX->q[i] >> 29) & 0x007fffff) + | 0x7fc00000; + else + GX->f[i] = EX->d[i]; + } + #else + GX->f[0] = EX->d[0]; + GX->f[1] = EX->d[1]; + #endif + GX->q[1] = 0; + fesetround(oldround); + } + break; case 0x5B: /* CVTPS2DQ Gx, Ex */ nextop = F8; GETEX(0); GETGX; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -1850,11 +1849,11 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) } break; - case 0x7C: { /* HADDPD Gx, Ex */ + case 0x7C: { /* HADDPD Gx, Ex */ nextop = F8; GETEX(0); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); if(isnan(GX->d[0])) { GX->q[0] |= 0x0008000000000000ULL; } else if(isnan(GX->d[1])) { @@ -1862,12 +1861,12 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) } else { GX->d[0] += GX->d[1]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; - } - if(EX==GX) { - GX->q[1] = GX->q[0]; - } else { - if(isnan(EX->d[0])) { - GX->q[1] = EX->q[0] | 0x0008000000000000ULL; + } + if(EX==GX) { + GX->q[1] = GX->q[0]; + } else { + if(isnan(EX->d[0])) { + GX->q[1] = EX->q[0] | 0x0008000000000000ULL; } else if(isnan(EX->d[1])) { GX->q[1] = EX->q[1] | 0x0008000000000000ULL; } else { @@ -1875,14 +1874,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL; } } - fesetround(oldround); - } - break; - case 0x7D: { /* HSUBPD Gx, Ex */ + fesetround(oldround); + } + break; + case 0x7D: { /* HSUBPD Gx, Ex */ nextop = F8; GETEX(0); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); if(isnan(GX->d[0])) { GX->q[0] |= 0x0008000000000000ULL; } else if(isnan(GX->d[1])) { @@ -1890,12 +1889,12 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) } else { GX->d[0] -= GX->d[1]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; - } - if(EX==GX) { - GX->q[1] = GX->q[0]; - } else { - if(isnan(EX->d[0])) { - GX->q[1] = EX->q[0] | 0x0008000000000000ULL; + } + if(EX==GX) { + GX->q[1] = GX->q[0]; + } else { + if(isnan(EX->d[0])) { + GX->q[1] = EX->q[0] | 0x0008000000000000ULL; } else if(isnan(EX->d[1])) { GX->q[1] = EX->q[1] | 0x0008000000000000ULL; } else { @@ -1903,9 +1902,9 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL; } } - fesetround(oldround); - } - break; + fesetround(oldround); + } + break; case 0x7E: /* MOVD Ed, Gx */ nextop = F8; GETED(0); @@ -2379,7 +2378,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xC4: /* PINSRW Gx,Ew,Ib */ nextop = F8; - GETED(1); + GETE2(1); GETGX; tmp8u = F8; GX->uw[tmp8u&7] = ED->word[0]; // only low 16bits @@ -2402,30 +2401,30 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GX->q[1] = eax1.q[1]; break; - case 0xC7: - CHECK_FLAGS(emu); - nextop = F8; - GETE8xw(0); - if (MODREG) - switch ((nextop >> 3) & 7) { - case 6: /* RDRAND Ew */ - case 7: /* RDSEED Ew */ - RESET_FLAGS(emu); - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - CLEAR_FLAG(F_PF); - CLEAR_FLAG(F_ZF); - CLEAR_FLAG(F_AF); - SET_FLAG(F_CF); - EW->word[0] = (uint16_t)get_random32(); - break; - default: - return 0; - } - else - return 0; - break; - + case 0xC7: + CHECK_FLAGS(emu); + nextop = F8; + GETE8xw(0); + if (MODREG) + switch ((nextop >> 3) & 7) { + case 6: /* RDRAND Ew */ + case 7: /* RDSEED Ew */ + RESET_FLAGS(emu); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + CLEAR_FLAG(F_ZF); + CLEAR_FLAG(F_AF); + SET_FLAG(F_CF); + EW->word[0] = (uint16_t)get_random32(); + break; + default: + return 0; + } + else + return 0; + break; + case 0xC8: case 0xC9: case 0xCA: @@ -2442,19 +2441,19 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) emu->regs[tmp8u].word[0] = 0; } break; - case 0xD0: { /* ADDSUBPD Gx, Ex */ + case 0xD0: { /* ADDSUBPD Gx, Ex */ nextop = F8; GETEX(0); GETGX; - int oldround = mxcsr_setround(emu); + int oldround = mxcsr_setround(emu); for(int i=0; i<2; ++i) { if(isnan(GX->d[i])) GX->q[i] |= 0x0008000000000000ULL; else if(isnan(EX->d[i])) GX->q[i] = EX->q[i] | 0x0008000000000000ULL; else { if(i==0) GX->d[0] -= EX->d[0]; else GX->d[1] += EX->d[1]; if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL; } } - fesetround(oldround); - } - break; + fesetround(oldround); + } + break; case 0xD1: /* PSRLW Gx, Ex */ nextop = F8; GETEX(0); diff --git a/src/emu/x64run66d9.c b/src/emu/x64run66d9.c index aee6f59ac..c4bf264c2 100644 --- a/src/emu/x64run66d9.c +++ b/src/emu/x64run66d9.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run66dd.c b/src/emu/x64run66dd.c index 19614b1f1..d50f29bb2 100644 --- a/src/emu/x64run66dd.c +++ b/src/emu/x64run66dd.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run66f0.c b/src/emu/x64run66f0.c index 25d196be5..842c568e1 100644 --- a/src/emu/x64run66f0.c +++ b/src/emu/x64run66f0.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -244,6 +243,177 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr) } break; + case 0xAB: /* BTS Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + if(MODREG) { + emu->error |= ERR_ILLEGAL; + return 0; + } + GETEW(0); + GETGW; + tmp16s = GW->sword[0]; + tmp8u = tmp16s & 15; + tmp16s >>= 4; + ED = (reg64_t*)((uintptr_t)ED + (tmp16s << 1)); + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) + if ((uintptr_t)ED & 1) { + do { + tmp32u = native_lock_read_b(&(ED->byte[tmp8u >> 3])); + if (tmp32u & (1 << (tmp8u & 7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1 << (tmp8u & 7)); + tmp32s = native_lock_write_b(&(ED->byte[tmp8u >> 3]), tmp32u); + CLEAR_FLAG(F_CF); + } + } while (tmp32s); + } else { + do { + tmp32u = native_lock_read_h(ED); + if (tmp32u & (1 << tmp8u)) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1 << tmp8u); + tmp32s = native_lock_write_h(ED, tmp32u); + CLEAR_FLAG(F_CF); + } + } while (tmp32s); + } + #else + pthread_mutex_lock(&my_context->mutex_lock); + if (ED->word[0] & (1 << tmp8u)) { + SET_FLAG(F_CF); + } else { + ED->word[0] ^= (1 << tmp8u); + CLEAR_FLAG(F_CF); + } + pthread_mutex_unlock(&my_context->mutex_lock); + #endif + if (BOX64ENV(dynarec_test)) { + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_PF); + } + break; + + case 0xB3: /* BTR Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + if(MODREG) { + emu->error |= ERR_ILLEGAL; + return 0; + } + GETEW(0); + GETGW; + tmp16s = GW->sword[0]; + tmp8u = tmp16s & 15; + tmp16s >>= 4; + ED = (reg64_t*)((uintptr_t)ED + (tmp16s << 1)); + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) + if ((uintptr_t)ED & 1) { + do { + tmp32u = native_lock_read_b(&(ED->byte[tmp8u >> 3])); + if (tmp32u & (1 << (tmp8u & 7))) { + SET_FLAG(F_CF); + tmp32u ^= (1 << (tmp8u & 7)); + tmp32s = native_lock_write_b(&(ED->byte[tmp8u >> 3]), tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while (tmp32s); + } else { + do { + tmp32u = native_lock_read_h(ED); + if (tmp32u & (1 << tmp8u)) { + SET_FLAG(F_CF); + tmp32u ^= (1 << tmp8u); + tmp32s = native_lock_write_h(ED, tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while (tmp32s); + } + #else + pthread_mutex_lock(&my_context->mutex_lock); + if (ED->word[0] & (1 << tmp8u)) { + SET_FLAG(F_CF); + ED->word[0] ^= (1 << tmp8u); + } else { + CLEAR_FLAG(F_CF); + } + pthread_mutex_unlock(&my_context->mutex_lock); + #endif + if (BOX64ENV(dynarec_test)) { + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_PF); + } + break; + + case 0xBB: /* BTC Ew,Gw */ + CHECK_FLAGS(emu); + nextop = F8; + if(MODREG) { + emu->error |= ERR_ILLEGAL; + return 0; + } + GETEW(0); + GETGW; + tmp16s = GW->sword[0]; + tmp8u = tmp16s & 15; + tmp16s >>= 4; + ED = (reg64_t*)((uintptr_t)ED + (tmp16s << 1)); + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) + if ((uintptr_t)ED & 1) { + do { + tmp32u = native_lock_read_b(&(ED->byte[tmp8u >> 3])); + if (tmp32u & (1 << (tmp8u & 7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + CLEAR_FLAG(F_CF); + } + tmp32u ^= (1 << (tmp8u & 7)); + tmp32s = native_lock_write_b(&(ED->byte[tmp8u >> 3]), tmp32u); + } while (tmp32s); + } else { + do { + tmp32u = native_lock_read_h(ED); + if (tmp32u & (1 << tmp8u)) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + CLEAR_FLAG(F_CF); + } + tmp32u ^= (1 << tmp8u); + tmp32s = native_lock_write_h(ED, tmp32u); + } while (tmp32s); + } + #else + pthread_mutex_lock(&my_context->mutex_lock); + if (ED->word[0] & (1 << tmp8u)) { + SET_FLAG(F_CF); + } else { + CLEAR_FLAG(F_CF); + } + ED->word[0] ^= (1 << tmp8u); + pthread_mutex_unlock(&my_context->mutex_lock); + #endif + if (BOX64ENV(dynarec_test)) { + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_PF); + } + break; + case 0xC1: /* XADD Gw,Ew */ nextop = F8; if(MODREG) { diff --git a/src/emu/x64run66f20f.c b/src/emu/x64run66f20f.c index b263302ee..0b39668aa 100644 --- a/src/emu/x64run66f20f.c +++ b/src/emu/x64run66f20f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run66f30f.c b/src/emu/x64run66f30f.c index bd6d3d33e..abd2d7baf 100644 --- a/src/emu/x64run66f30f.c +++ b/src/emu/x64run66f30f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 23fe838af..6e8c41636 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include @@ -403,6 +402,32 @@ reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t return (reg64_t*)test->mem; } } +reg64_t* TestEd1(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 1; + test->memaddr = (uintptr_t)ret; + *(uint8_t*)test->mem = ret->byte[0]; + return (reg64_t*)test->mem; + } +} +reg64_t* TestEd2(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &test->emu->regs[(m&0x07)+(rex.b<<3)]; + } else { + reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta); + test->memsize = 2; + test->memaddr = (uintptr_t)ret; + *(uint16_t*)test->mem = ret->word[0]; + return (reg64_t*)test->mem; + } +} reg64_t* TestEd4(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta) { if(rex.is67 && rex.is32bits) { diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index d244d203f..f5903d8f6 100644 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -131,6 +131,8 @@ reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t de reg64_t* TestEbO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +reg64_t* TestEd1(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); +reg64_t* TestEd2(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* TestEd4(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); reg64_t* TestEd4O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset); reg64_t* TestEd8(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta); diff --git a/src/emu/x64runavx.c b/src/emu/x64runavx.c index 36ac7031a..daed5d04f 100644 --- a/src/emu/x64runavx.c +++ b/src/emu/x64runavx.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavx0f.c b/src/emu/x64runavx0f.c index 11a86ac53..b6a973e1b 100644 --- a/src/emu/x64runavx0f.c +++ b/src/emu/x64runavx0f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -399,26 +398,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] + EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] + EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -434,26 +433,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] * EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] * EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -469,7 +468,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) if (vex.l) { #ifdef RV64 for (int i = 1; i >= 0; --i) { - if (isnanf(EX->f[i + 2])) + if (isnan(EX->f[i + 2])) GY->q[i] = ((uint64_t)(EX->ud[i + 2] & 0x80000000) << 32) | ((uint64_t)(EX->ud[i + 2] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -484,7 +483,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GY->u128 = 0; #ifdef RV64 for (int i = 1; i >= 0; --i) { - if (isnanf(EX->f[i])) + if (isnan(EX->f[i])) GX->q[i] = ((uint64_t)(EX->ud[i] & 0x80000000) << 32) | ((uint64_t)(EX->ud[i] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -526,26 +525,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] - EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] - EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -560,7 +559,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; for(int i=0; i<4; ++i) - if (isnanf(VX->f[i]) || isnanf(EX->f[i]) || islessequal(EX->f[i], VX->f[i])) + if (isnan(VX->f[i]) || isnan(EX->f[i]) || islessequal(EX->f[i], VX->f[i])) GX->f[i] = EX->f[i]; else GX->f[i] = VX->f[i]; @@ -568,7 +567,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEY; GETVY; for(int i=0; i<4; ++i) - if (isnanf(VY->f[i]) || isnanf(EY->f[i]) || islessequal(EY->f[i], VY->f[i])) + if (isnan(VY->f[i]) || isnan(EY->f[i]) || islessequal(EY->f[i], VY->f[i])) GY->f[i] = EY->f[i]; else GY->f[i] = VY->f[i]; @@ -583,26 +582,26 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGY; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; - } else if(isnanf(EX->f[i])) { + } else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } else { GX->f[i] = VX->f[i] / EX->f[i]; - if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; + if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { GETEY; GETVY; for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; - } else if(isnanf(EY->f[i])) { + } else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } else { GY->f[i] = VY->f[i] / EY->f[i]; - if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; + if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else @@ -617,7 +616,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; for(int i=0; i<4; ++i) - if (isnanf(VX->f[i]) || isnanf(EX->f[i]) || isgreaterequal(EX->f[i], VX->f[i])) + if (isnan(VX->f[i]) || isnan(EX->f[i]) || isgreaterequal(EX->f[i], VX->f[i])) GX->f[i] = EX->f[i]; else GX->f[i] = VX->f[i]; @@ -625,7 +624,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEY; GETVY; for(int i=0; i<4; ++i) - if (isnanf(VY->f[i]) || isnanf(EY->f[i]) || isgreaterequal(EY->f[i], VY->f[i])) + if (isnan(VY->f[i]) || isnan(EY->f[i]) || isgreaterequal(EY->f[i], VY->f[i])) GY->f[i] = EY->f[i]; else GY->f[i] = VY->f[i]; diff --git a/src/emu/x64runavx0f38.c b/src/emu/x64runavx0f38.c index bae5b3208..137432ef5 100644 --- a/src/emu/x64runavx0f38.c +++ b/src/emu/x64runavx0f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavx660f.c b/src/emu/x64runavx660f.c index 9123f7945..9ab9be574 100644 --- a/src/emu/x64runavx660f.c +++ b/src/emu/x64runavx660f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -440,7 +439,7 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGX; GETGY; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -471,7 +470,7 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) if(vex.l) { GETEY; for(int i=0; i<4; ++i) { - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { diff --git a/src/emu/x64runavx660f38.c b/src/emu/x64runavx660f38.c index d9292be82..bc19c0f63 100644 --- a/src/emu/x64runavx660f38.c +++ b/src/emu/x64runavx660f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -674,7 +673,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case 0x20: /* VPMOVSXBW Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -687,7 +686,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x21: /* VPMOVSXBD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -700,7 +699,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x22: /* VPMOVSXBQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX4(0); else GETEX2(0); GETGX; GETGY; if(vex.l) @@ -713,7 +712,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x23: /* VPMOVSXWD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -726,7 +725,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x24: /* VPMOVSXWQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -739,7 +738,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x25: /* VPMOVSXDQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -914,7 +913,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x30: /* VPMOVZXBW Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -927,7 +926,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x31: /* VPMOVZXBD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -940,7 +939,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x32: /* VPMOVZXBQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX4(0); else GETEX2(0); GETGX; GETGY; if(vex.l) @@ -953,7 +952,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x33: /* VPMOVZXWD Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) @@ -966,7 +965,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x34: /* VPMOVZXWQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX8(0); else GETEX4(0); GETGX; GETGY; if(vex.l) @@ -979,7 +978,7 @@ uintptr_t RunAVX_660F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; case 0x35: /* VPMOVZXDQ Gx, Ex */ nextop = F8; - GETEX(0); + if(vex.l) GETEX(0); else GETEX8(0); GETGX; GETGY; if(vex.l) diff --git a/src/emu/x64runavx660f3a.c b/src/emu/x64runavx660f3a.c index ea78c745a..eb7d74311 100644 --- a/src/emu/x64runavx660f3a.c +++ b/src/emu/x64runavx660f3a.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -191,7 +190,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) fesetround(FE_TONEAREST); for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -202,7 +201,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Down: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -211,7 +210,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Up: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -220,7 +219,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Chop: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; else #endif @@ -235,7 +234,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) fesetround(FE_TONEAREST); for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -246,7 +245,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Down: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -255,7 +254,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Up: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -264,7 +263,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) case ROUND_Chop: for(int i=0; i<4; ++i) #ifdef RV64 - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) GY->ud[i] = EY->ud[i] | 0x00400000; else #endif @@ -378,7 +377,7 @@ uintptr_t RunAVX_660F3A(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGX; GETVX; GETGY; tmp8u = F8; // ignoring bit 3 interupt thingy #ifdef RV64 - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[0] = EX->ud[0] | 0x00400000; } else #endif diff --git a/src/emu/x64runavxf20f.c b/src/emu/x64runavxf20f.c index 5b63d208d..7a73caee6 100644 --- a/src/emu/x64runavxf20f.c +++ b/src/emu/x64runavxf20f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -368,9 +367,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) int oldround = mxcsr_setround(emu); for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; - else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; - else { GX->f[i] = VX->f[j] + VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; + else if(isnan(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; + else { GX->f[i] = VX->f[j] + VX->f[j+1]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(EX==VX) { GX->ud[2] = GX->ud[0]; @@ -378,17 +377,17 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; - else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; - else { GX->f[i+2] = EX->f[j] + EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } + if(isnan(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; + else if(isnan(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; + else { GX->f[i+2] = EX->f[j] + EX->f[j+1]; if(isnan(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } } } if(vex.l) { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; - else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; - else { GY->f[i] = VY->f[j] + VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; } + if(isnan(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; + else if(isnan(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; + else { GY->f[i] = VY->f[j] + VY->f[j+1]; if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } if(EY==VY) { GY->ud[2] = GY->ud[0]; @@ -396,9 +395,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; - else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; - else { GY->f[i+2] = EY->f[j] + EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } + if(isnan(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; + else if(isnan(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; + else { GY->f[i+2] = EY->f[j] + EY->f[j+1]; if(isnan(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } } } } else @@ -426,9 +425,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) int oldround = mxcsr_setround(emu); for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; - else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; - else { GX->f[i] = VX->f[j] - VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000; + else if(isnan(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000; + else { GX->f[i] = VX->f[j] - VX->f[j+1]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if (EX == VX) { GX->ud[2] = GX->ud[0]; @@ -436,17 +435,17 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; - else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; - else { GX->f[i+2] = EX->f[j] - EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } + if(isnan(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000; + else if(isnan(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000; + else { GX->f[i+2] = EX->f[j] - EX->f[j+1]; if(isnan(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; } } } if (vex.l) { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; - else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; - else { GY->f[i] = VY->f[j] - VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; } + if(isnan(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000; + else if(isnan(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000; + else { GY->f[i] = VY->f[j] - VY->f[j+1]; if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } if (EY == VY) { GY->ud[2] = GY->ud[0]; @@ -454,9 +453,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } else { for(int i=0; i<2; ++i) { int j = i*2; - if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; - else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; - else { GY->f[i+2] = EY->f[j] - EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } + if(isnan(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000; + else if(isnan(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000; + else { GY->f[i+2] = EY->f[j] - EY->f[j+1]; if(isnan(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; } } } } else @@ -509,15 +508,15 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) } int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; } - else if(isnanf(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } - else { if(i&1) GX->f[i] = VX->f[i] + EX->f[i]; else GX->f[i] = VX->f[i] - EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; } + else if(isnan(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; } + else { if(i&1) GX->f[i] = VX->f[i] + EX->f[i]; else GX->f[i] = VX->f[i] - EX->f[i]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } if(vex.l) { for(int i=0; i<4; ++i) { - if(isnanf(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; } - else if(isnanf(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } - else { if(i&1) GY->f[i] = VY->f[i] + EY->f[i]; else GY->f[i] = VY->f[i] - EY->f[i]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; } + if(isnan(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; } + else if(isnan(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; } + else { if(i&1) GY->f[i] = VY->f[i] + EY->f[i]; else GY->f[i] = VY->f[i] - EY->f[i]; if(isnan(GY->f[i])) GY->ud[i] |= 0x80000000; } } } else GY->u128 = 0; diff --git a/src/emu/x64runavxf20f38.c b/src/emu/x64runavxf20f38.c index 4a8d9a923..23ff84df3 100644 --- a/src/emu/x64runavxf20f38.c +++ b/src/emu/x64runavxf20f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavxf20f3a.c b/src/emu/x64runavxf20f3a.c index e53c8fb71..720ab7e7d 100644 --- a/src/emu/x64runavxf20f3a.c +++ b/src/emu/x64runavxf20f3a.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavxf30f.c b/src/emu/x64runavxf30f.c index f7bad00f1..ca4fd014b 100644 --- a/src/emu/x64runavxf30f.c +++ b/src/emu/x64runavxf30f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -140,13 +139,13 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEX(0); GETGD; if (rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else GD->sq[0] = EX->f[0]; } else { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { mxcsr_raise_invalid(emu); GD->dword[0] = 0x80000000; } else @@ -159,7 +158,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETEX(0); GETGD; if(rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else @@ -182,7 +181,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) break; } } else { - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -220,7 +219,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) int oldround = mxcsr_setround(emu); if(EX->f[0]<0.0 ) GX->f[0] = -NAN; - else if(isnanf(EX->f[0])) + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else GX->f[0] = sqrt(EX->f[0]); @@ -271,9 +270,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] + EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] + EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; @@ -289,9 +288,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] * EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] * EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; @@ -307,7 +306,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; #ifdef RV64 - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) GX->q[0] = ((uint64_t)(EX->ud[0] & 0x80000000) << 32) | ((uint64_t)(EX->ud[0] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -325,7 +324,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETGX; GETGY; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else tmp64s = EX->f[i]; @@ -339,7 +338,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) if(vex.l) { GETEY; for(int i=0; i<4; ++i) { - if(isnanf(EY->f[i])) + if(isnan(EY->f[i])) tmp64s = INT32_MIN; else tmp64s = EY->f[i]; @@ -360,9 +359,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] - EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] - EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; @@ -395,9 +394,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GETVX; GETGY; int oldround = mxcsr_setround(emu); - if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = VX->f[0] / EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = VX->f[0] / EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } if(GX!=VX) { GX->ud[1] = VX->ud[1]; GX->q[1] = VX->q[1]; diff --git a/src/emu/x64runavxf30f38.c b/src/emu/x64runavxf30f38.c index cd15c5aae..3084606a2 100644 --- a/src/emu/x64runavxf30f38.c +++ b/src/emu/x64runavxf30f38.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runavxf30f3a.c b/src/emu/x64runavxf30f3a.c index c67fcd9b8..caacf91c0 100644 --- a/src/emu/x64runavxf30f3a.c +++ b/src/emu/x64runavxf30f3a.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rund8.c b/src/emu/x64rund8.c index eec0a27e5..092ca2863 100644 --- a/src/emu/x64rund8.c +++ b/src/emu/x64rund8.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c index f92592235..ef652ee70 100644 --- a/src/emu/x64rund9.c +++ b/src/emu/x64rund9.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runda.c b/src/emu/x64runda.c index 0c4b869ac..c9e0b520f 100644 --- a/src/emu/x64runda.c +++ b/src/emu/x64runda.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rundb.c b/src/emu/x64rundb.c index 5c12a9bd5..0998a035a 100644 --- a/src/emu/x64rundb.c +++ b/src/emu/x64rundb.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -32,6 +31,7 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) { uint8_t nextop; int32_t tmp32s; + double tmpd; reg64_t *oped; #ifdef TEST_INTERPRETER x64emu_t*emu = test->emu; @@ -148,30 +148,33 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 1: /* FISTTP Ed, ST0 */ GETE4(0); - if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d)) { + tmpd = trunc(ST0.d); + if(tmpd > (double)0x7fffffff || tmpd < -(double)0x80000000U || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sdword[0] = 0x80000000; } else - ED->sdword[0] = ST0.d; + ED->sdword[0] = tmpd; fpu_do_pop(emu); break; case 2: /* FIST Ed, ST0 */ GETE4(0); - if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)0x7fffffff || tmpd < -(double)0x80000000U || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sdword[0] = 0x80000000; } else { - volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR + volatile int32_t tmp = (int32_t)tmpd; // tmp to avoid BUS ERROR ED->sdword[0] = tmp; } break; case 3: /* FISTP Ed, ST0 */ GETE4(0); - if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)0x7fffffff || tmpd < -(double)0x80000000U || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sdword[0] = 0x80000000; } else { - volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR + volatile int32_t tmp = (int32_t)tmpd; // tmp to avoid BUS ERROR ED->sdword[0] = tmp; } fpu_do_pop(emu); diff --git a/src/emu/x64rundc.c b/src/emu/x64rundc.c index f42bc67b3..56447e83b 100644 --- a/src/emu/x64rundc.c +++ b/src/emu/x64rundc.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rundd.c b/src/emu/x64rundd.c index 059e239c6..acd9c2898 100644 --- a/src/emu/x64rundd.c +++ b/src/emu/x64rundd.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64runde.c b/src/emu/x64runde.c index 2ff42e124..5f0bbb31a 100644 --- a/src/emu/x64runde.c +++ b/src/emu/x64runde.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64rundf.c b/src/emu/x64rundf.c index 5170aff36..9bb19df71 100644 --- a/src/emu/x64rundf.c +++ b/src/emu/x64rundf.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -30,6 +29,7 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) { uint8_t nextop; int16_t tmp16s; + double tmpd; int64_t tmp64s; reg64_t *oped; #ifdef TEST_INTERPRETER @@ -107,29 +107,31 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 1: /* FISTTP Ew, ST0 */ GETEW(0); - tmp16s = ST0.d; - if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d)) { + tmpd = trunc(ST0.d); + if(tmpd > (double)(int32_t)0x7fff || tmpd < -(double)(int32_t)0x8000 || !isfinite(tmpd)) { fpu_raise_invalid(emu); EW->sword[0] = 0x8000; } else - EW->sword[0] = tmp16s; + EW->sword[0] = tmpd; fpu_do_pop(emu); break; case 2: /* FIST Ew, ST0 */ GETEW(0); - if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)(int32_t)0x7fff || tmpd < -(double)(int32_t)0x8000 || !isfinite(tmpd)) { fpu_raise_invalid(emu); EW->sword[0] = 0x8000; } else - EW->sword[0] = fpu_round(emu, ST0.d); + EW->sword[0] = tmpd; break; case 3: /* FISTP Ew, ST0 */ GETEW(0); - if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd > (double)(int32_t)0x7fff || tmpd < -(double)(int32_t)0x8000 || !isfinite(tmpd)) { fpu_raise_invalid(emu); EW->sword[0] = 0x8000; } else - EW->sword[0] = fpu_round(emu, ST0.d); + EW->sword[0] = tmpd; fpu_do_pop(emu); break; case 4: /* FBLD ST0, tbytes */ @@ -155,11 +157,12 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr) if(STll(0).sref==ST(0).sq) ED->sq[0] = STll(0).sq; else { - if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d)) { + tmpd = fpu_round(emu, ST0.d); + if(tmpd >= (double)0x8000000000000000LL || tmpd < -(double)0x8000000000000000LL || !isfinite(tmpd)) { fpu_raise_invalid(emu); ED->sq[0] = 0x8000000000000000LL; } else - ED->sq[0] = fpu_round(emu, ST0.d); + ED->sq[0] = tmpd; } fpu_do_pop(emu); break; diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c index c17bf60ac..05b10c371 100644 --- a/src/emu/x64runf0.c +++ b/src/emu/x64runf0.c @@ -1,5 +1,4 @@ -// SPDX-License-Identifier: MIT -#define _GNU_SOURCE +// SPDX-License-Identifier: MIT #include #include #include @@ -79,7 +78,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) GETED(0); \ GETGD; \ if(F) {CHECK_FLAGS(emu); eflags=emu->eflags;} \ - if(((uintptr_t)ED)&(rex.w?7:3)) { \ + if(((uintptr_t)ED)&(rex.w?7:3)) { \ if(rex.w) { \ do { \ if(F) emu->eflags = eflags; \ @@ -178,35 +177,63 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) #else ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); #endif -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + CLEAR_FLAG(F_CF); + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + CLEAR_FLAG(F_CF); + } + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { tmp8u&=63; @@ -226,7 +253,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) } } pthread_mutex_unlock(&my_context->mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -373,33 +400,61 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); #endif tmp8u&=rex.w?63:31; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) - if(rex.w) - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { if(ED->q[0] & (1ULL<mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -438,20 +493,34 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32s = 0; + } else { + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + CLEAR_FLAG(F_CF); + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<mutex_lock); if(rex.w) { tmp8u&=63; @@ -500,7 +569,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) } } pthread_mutex_unlock(&my_context->mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -512,35 +581,63 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { - do { - tmp8u&=63; - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) { + SET_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } else { + CLEAR_FLAG(F_CF); + tmp32s = 0; + } + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { tmp8u&=63; @@ -558,7 +655,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CLEAR_FLAG(F_CF); } pthread_mutex_unlock(&my_context->mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -570,18 +667,30 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) CHECK_FLAGS(emu); GETED(1); tmp8u = F8; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) + #if defined(DYNAREC) && !defined(TEST_INTERPRETER) if(rex.w) { tmp8u&=63; - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<mutex_lock); if(rex.w) { tmp8u&=63; @@ -624,7 +733,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) ED->dword[0] ^= (1<mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); @@ -659,31 +768,55 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr) ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2))); #endif tmp8u&=rex.w?63:31; -#if defined(DYNAREC) && !defined(TEST_INTERPRETER) - if(rex.w) - do { - tmp64u = native_lock_read_dd(ED); - if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } while(tmp32s); + } else { + do { + tmp64u = native_lock_read_dd(ED); + if(tmp64u & (1LL<byte[tmp8u>>3]); + if(tmp32u & (1<<(tmp8u&7))) + SET_FLAG(F_CF); + else + CLEAR_FLAG(F_CF); + tmp32u ^= (1<<(tmp8u&7)); + tmp32s = native_lock_write_b(&ED->byte[tmp8u>>3], tmp32u); + } while(tmp32s); + } else { + do { + tmp32u = native_lock_read_d(ED); + if(tmp32u & (1<mutex_lock); if(rex.w) { if(ED->q[0] & (1ULL<dword[0] ^= (1<mutex_lock); -#endif + #endif if(BOX64ENV(dynarec_test)) { CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index 543e98487..af15a4825 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -373,40 +372,40 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); eax1 = *GX; - if(isnanf(eax1.f[0])) { + if(isnan(eax1.f[0])) { GX->ud[0] = eax1.ud[0] | 0x00400000; - } else if(isnanf(eax1.f[1])) { + } else if(isnan(eax1.f[1])) { GX->ud[0] = eax1.ud[1] | 0x00400000; } else { GX->f[0] = eax1.f[0] + eax1.f[1]; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } - if(isnanf(eax1.f[2])) { + if(isnan(eax1.f[2])) { GX->ud[1] = eax1.ud[2] | 0x00400000; - } else if(isnanf(eax1.f[3])) { + } else if(isnan(eax1.f[3])) { GX->ud[1] = eax1.ud[3] | 0x00400000; } else { GX->f[1] = eax1.f[2] + eax1.f[3]; - if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000; + if(isnan(GX->f[1])) GX->ud[1] |= 0x80000000; } if(EX==GX) { GX->q[1] = GX->q[0]; } else { - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[2] = EX->ud[0] | 0x00400000; - } else if(isnanf(EX->f[1])) { + } else if(isnan(EX->f[1])) { GX->ud[2] = EX->ud[1] | 0x00400000; } else { GX->f[2] = EX->f[0] + EX->f[1]; - if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000; + if(isnan(GX->f[2])) GX->ud[2] |= 0x80000000; } - if(isnanf(EX->f[2])) { + if(isnan(EX->f[2])) { GX->ud[3] = EX->ud[2] | 0x00400000; - } else if(isnanf(EX->f[3])) { + } else if(isnan(EX->f[3])) { GX->ud[3] = EX->ud[3] | 0x00400000; } else { GX->f[3] = EX->f[2] + EX->f[3]; - if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000; + if(isnan(GX->f[3])) GX->ud[3] |= 0x80000000; } } fesetround(oldround); @@ -418,40 +417,40 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); eax1 = *GX; - if(isnanf(eax1.f[0])) { + if(isnan(eax1.f[0])) { GX->ud[0] = eax1.ud[0] | 0x00400000; - } else if(isnanf(eax1.f[1])) { + } else if(isnan(eax1.f[1])) { GX->ud[0] = eax1.ud[1] | 0x00400000; } else { GX->f[0] = eax1.f[0] - eax1.f[1]; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } - if(isnanf(eax1.f[2])) { + if(isnan(eax1.f[2])) { GX->ud[1] = eax1.ud[2] | 0x00400000; - } else if(isnanf(eax1.f[3])) { + } else if(isnan(eax1.f[3])) { GX->ud[1] = eax1.ud[3] | 0x00400000; } else { GX->f[1] = eax1.f[2] - eax1.f[3]; - if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000; + if(isnan(GX->f[1])) GX->ud[1] |= 0x80000000; } if(EX==GX) { GX->q[1] = GX->q[0]; } else { - if(isnanf(EX->f[0])) { + if(isnan(EX->f[0])) { GX->ud[2] = EX->ud[0] | 0x00400000; - } else if(isnanf(EX->f[1])) { + } else if(isnan(EX->f[1])) { GX->ud[2] = EX->ud[1] | 0x00400000; } else { GX->f[2] = EX->f[0] - EX->f[1]; - if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000; + if(isnan(GX->f[2])) GX->ud[2] |= 0x80000000; } - if(isnanf(EX->f[2])) { + if(isnan(EX->f[2])) { GX->ud[3] = EX->ud[2] | 0x00400000; - } else if(isnanf(EX->f[3])) { + } else if(isnan(EX->f[3])) { GX->ud[3] = EX->ud[3] | 0x00400000; } else { GX->f[3] = EX->f[2] - EX->f[3]; - if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000; + if(isnan(GX->f[3])) GX->ud[3] |= 0x80000000; } } fesetround(oldround); @@ -511,9 +510,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; int oldround = mxcsr_setround(emu); for(int i=0; i<4; ++i) { - if(isnanf(GX->f[i])) GX->ud[i] |= 0x00400000; - else if(isnanf(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; - else { if(i&1) GX->f[i] += EX->f[i]; else GX->f[i] -= EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; } + if(isnan(GX->f[i])) GX->ud[i] |= 0x00400000; + else if(isnan(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000; + else { if(i&1) GX->f[i] += EX->f[i]; else GX->f[i] -= EX->f[i]; if(isnan(GX->f[i])) GX->ud[i] |= 0x80000000; } } fesetround(oldround); } diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index eaea9e18a..b049711b6 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -109,16 +108,16 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x2C: /* CVTTSS2SI Gd, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGD; if (rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else GD->sq[0] = EX->f[0]; } else { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffff) { mxcsr_raise_invalid(emu); GD->dword[0] = 0x80000000; } else @@ -128,10 +127,10 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x2D: /* CVTSS2SI Gd, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGD; if(rex.w) { - if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { + if(isnan(EX->f[0]) || isinf(EX->f[0]) || EX->f[0]>=(float)0x7fffffffffffffffLL) { mxcsr_raise_invalid(emu); GD->q[0] = 0x8000000000000000LL; } else @@ -154,7 +153,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; } } else { - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) tmp64s = INT32_MIN; else switch(emu->mxcsr.f.MXCSR_RC) { @@ -236,7 +235,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GETGX; if (EX->f[0]<0) GX->f[0] = -NAN; - else if (isnanf(EX->f[0])) + else if (isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else{ int oldround = mxcsr_setround(emu); @@ -263,43 +262,43 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) nextop = F8; GETEX(0); GETGX; - if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; - else { GX->f[0] = 1.0f/EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + else { GX->f[0] = 1.0f/EX->f[0]; if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x58: /* ADDSS Gx, Ex */ nextop = F8; GETEX(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] += EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x59: /* MULSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] *= EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x5A: /* CVTSS2SD Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; #ifdef RV64 - if(isnanf(EX->f[0])) + if(isnan(EX->f[0])) GX->q[0] = ((uint64_t)(EX->ud[0] & 0x80000000) << 32) | ((uint64_t)(EX->ud[0] & 0x007fffff) << 29) | 0x7ff8000000000000ULL; @@ -314,7 +313,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GETEX(0); GETGX; for(int i=0; i<4; ++i) { - if(isnanf(EX->f[i])) + if(isnan(EX->f[i])) tmp64s = INT32_MIN; else tmp64s = EX->f[i]; @@ -328,38 +327,38 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) break; case 0x5C: /* SUBSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] -= EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x5D: /* MINSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if(isnan(GX->f[0]) || isnan(EX->f[0]) || islessequal(EX->f[0], GX->f[0])) GX->f[0] = EX->f[0]; break; case 0x5E: /* DIVSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; - if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000; - else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; + if(isnan(GX->f[0])) GX->ud[0] |= 0x00400000; + else if(isnan(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000; else { int oldround = mxcsr_setround(emu); GX->f[0] /= EX->f[0]; fesetround(oldround); - if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; } + if(isnan(GX->f[0])) GX->ud[0] |= 0x80000000; } break; case 0x5F: /* MAXSS Gx, Ex */ nextop = F8; - GETEX(0); + GETEX4(0); GETGX; if (isnan(GX->f[0]) || isnan(EX->f[0]) || isgreaterequal(EX->f[0], GX->f[0])) GX->f[0] = EX->f[0]; @@ -552,19 +551,20 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step) GX->ud[0]=(tmp8s)?0xffffffff:0; break; - case 0xC7: - CHECK_FLAGS(emu); - nextop = F8; - GETE8xw(0); - switch(tmp8u&7) { - case 6: /* RDPID Ed */ - ED->q[0] = helper_getcpu(emu); - SET_FLAG(F_CF); - break; - default: - return 0; - } - GX->ud[0]=(tmp8s)?0xffffffff:0; + case 0xC7: + nextop = F8; + tmp8u = nextop >> 3; + switch(tmp8u&7) { + case 7: /* RDPID Ed */ + if (!MODREG) { + return 0; + } + GETED(0); + ED->q[0] = helper_getcpu(emu); + break; + default: + return 0; + } break; case 0xD6: /* MOVQ2DQ Gx, Em */ diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c index e5f29a7bc..5c0f54a7b 100644 --- a/src/emu/x64syscall.c +++ b/src/emu/x64syscall.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include @@ -431,8 +430,8 @@ typedef struct x86_linux_dirent_s { } x86_linux_dirent_t; typedef struct nat_linux_dirent64_s { - ino64_t d_ino; - off64_t d_off; + ino_t d_ino; + off_t d_off; unsigned short d_reclen; unsigned char d_type; char d_name[]; diff --git a/src/emu/x64test.c b/src/emu/x64test.c index 36a04c380..259d43424 100644 --- a/src/emu/x64test.c +++ b/src/emu/x64test.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c index a427186eb..6ebe541b7 100644 --- a/src/emu/x64tls.c +++ b/src/emu/x64tls.c @@ -137,7 +137,7 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_32_t* td, int size) static const char* arch_prctl_param(int code) { - static char ret[10] = {0}; + static char ret[12] = {0}; switch (code) { case 0x1001: return "ARCH_SET_GS"; case 0x1002: return "ARCH_SET_FS"; diff --git a/src/emu/x86int3.c b/src/emu/x86int3.c index 8bd32a73f..4e86ff038 100755 --- a/src/emu/x86int3.c +++ b/src/emu/x86int3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/emu/x86syscall.c b/src/emu/x86syscall.c index 7e831b423..267259246 100755 --- a/src/emu/x86syscall.c +++ b/src/emu/x86syscall.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/emu/x86syscall_32.c b/src/emu/x86syscall_32.c index edac2ae4d..e0ab78bd9 100644 --- a/src/emu/x86syscall_32.c +++ b/src/emu/x86syscall_32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/include/box64context.h b/src/include/box64context.h index 6de8ae6e9..49c065904 100644 --- a/src/include/box64context.h +++ b/src/include/box64context.h @@ -79,6 +79,8 @@ typedef struct needed_libs_s { library_t** libs; path_collection_t* rpath; int nb_done; + char** nonstaticnames; + int ns_size; } needed_libs_t; void free_neededlib(needed_libs_t* needed); @@ -88,6 +90,7 @@ void add1_neededlib(needed_libs_t* needed); void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name); void add1lib_neededlib_name(needed_libs_t* needed, library_t* lib, const char* name); void add1libref_neededlib(needed_libs_t* needed, library_t* lib); +char* add1nsname(needed_libs_t* needed, char* nsname); typedef struct base_segment_s { uintptr_t base; diff --git a/src/include/debug.h b/src/include/debug.h index e11f471cf..f6b3b8673 100644 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -12,7 +12,7 @@ typedef struct box64context_s box64context_t; extern box64env_t box64env; extern box64env_t* cur_box64env; -#define X86_PAGE_SIZE 4096UL +#define X86_PAGE_SIZE 4096ULL #define ALIGN(p) (((p)+box64_pagesize-1)&~(box64_pagesize-1)) #define ALIGN_DOWN(p) ((p)&~(box64_pagesize-1)) diff --git a/src/include/dynablock.h b/src/include/dynablock.h index fb21af301..0adaa6dec 100644 --- a/src/include/dynablock.h +++ b/src/include/dynablock.h @@ -19,7 +19,8 @@ dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64c // Handling of Dynarec block (i.e. an exectable chunk of x64 translated code) dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits); // return NULL if block is not found / cannot be created. Don't create if create==0 -dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new); +#define SEARCHED_NO_DYNABLOCK ((dynablock_t*)-1ULL) +dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int need_lock, int is32bits, int is_new, dynablock_t* block); void FlushZombieDynablocks(void); // for use in signal handler diff --git a/src/include/dynarec_native.h b/src/include/dynarec_native.h index dcf9ca1f3..c7ff8f5dc 100644 --- a/src/include/dynarec_native.h +++ b/src/include/dynarec_native.h @@ -7,12 +7,9 @@ typedef struct x64emu_s x64emu_t; typedef struct instsize_s instsize_t; #define MAX_INSTS 32760 -#define LEAFCALL_INSTSIZE_SCRATCH 32768 void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size); -void* dynarec_get_leaf_embedded(void* owner, int ninst); - void CancelBlock64(int need_lock); dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int noalt); diff --git a/src/include/elfloader.h b/src/include/elfloader.h index 7dee4434e..ef564b722 100644 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -54,6 +54,7 @@ uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h); uintptr_t GetLastByte(elfheader_t* h); void AddSymbols(lib_t *maplib, elfheader_t* h); int NeededLibs(elfheader_t* h); +char* ExpandNeededLibs(elfheader_t* h, char* rpath); int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu); needed_libs_t* GetELfNeededLibs(elfheader_t* h); uintptr_t GetElfInit(elfheader_t* h); diff --git a/src/include/hostext.h b/src/include/hostext.h index 513e3029d..6faed3463 100644 --- a/src/include/hostext.h +++ b/src/include/hostext.h @@ -20,6 +20,9 @@ typedef union cpu_ext_s { uint64_t frintts : 1; uint64_t afp : 1; uint64_t rndr : 1; + uint64_t lrcpc : 1; + uint64_t lrcpc2 : 1; + uint64_t lrcpc3 : 1; #elif defined(RV64) uint64_t vlen : 8; // Not *8, 8bits should be enugh? that's 2048 vector uint64_t zba : 1; diff --git a/src/include/os.h b/src/include/os.h index e2f8d50c3..f66400db3 100644 --- a/src/include/os.h +++ b/src/include/os.h @@ -98,14 +98,6 @@ const char* GetBridgeName(void* p); #define PROT_WRITE 0x2 #define PROT_EXEC 0x4 -#if defined(__clang__) && !defined(_WIN32) -extern int isinff(float); -extern int isnanf(float); -#elif defined(_WIN32) -#define isnanf isnan -#define isinff isinf -#endif - void PrintfFtrace(int prefix, const char* fmt, ...); void* GetEnv(const char* name); diff --git a/src/include/sigtools.h b/src/include/sigtools.h index fc607ff93..77e338368 100644 --- a/src/include/sigtools.h +++ b/src/include/sigtools.h @@ -51,7 +51,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, int unlockMutex(); int checkMutex(uint32_t mask); -int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits); +int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits, void* ucntx); void adjustregs(x64emu_t* emu, void* pc); void copyUCTXreg2Emu(x64emu_t* emu, ucontext_t* p, dynablock_t* db, uintptr_t ip); diff --git a/src/librarian/globalsymbols.c b/src/librarian/globalsymbols.c index c328ad061..42c904770 100644 --- a/src/librarian/globalsymbols.c +++ b/src/librarian/globalsymbols.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/librarian/globalsymbols32.c b/src/librarian/globalsymbols32.c index 4d565fcfd..5264c59f0 100644 --- a/src/librarian/globalsymbols32.c +++ b/src/librarian/globalsymbols32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/librarian/library.c b/src/librarian/library.c index 1c5b04459..8aa9ad605 100644 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #define __USE_GNU #include #include @@ -1323,6 +1322,13 @@ void free_neededlib(needed_libs_t* needed) FreeCollection(needed->rpath); box_free(needed->rpath); } + if(needed->nonstaticnames) { + for(int i=0; ins_size; ++i) + box_free(needed->nonstaticnames[i]); + box_free(needed->nonstaticnames); + needed->ns_size = 0; + needed->nonstaticnames = NULL; + } box_free(needed); } void add1_neededlib(needed_libs_t* needed) @@ -1406,8 +1412,30 @@ needed_libs_t* copy_neededlib(needed_libs_t* needed) ret->names = (char**)box_calloc(ret->cap, sizeof(char*)); memcpy(ret->libs, needed->libs, ret->size*sizeof(library_t*)); memcpy(ret->names, needed->names, ret->size*sizeof(char*)); + if(needed->nonstaticnames) { + ret->ns_size = needed->ns_size; + ret->nonstaticnames = (char**)box_malloc(ret->ns_size*sizeof(char*)); + for(int i=0; ins_size; ++i) + ret->nonstaticnames[i] = box_strdup(needed->nonstaticnames[i]); + } return ret; } +char* add1nsname(needed_libs_t* needed, char* nsname) +{ + if(!needed->ns_size) { + needed->ns_size = 1; + needed->nonstaticnames = (char**)box_malloc(needed->ns_size*sizeof(char*)); + needed->nonstaticnames[0] = nsname; + return needed->nonstaticnames[0]; + } + for(int i=0; ins_size; ++i) + if(!strcmp(needed->nonstaticnames[i], nsname)) + return needed->nonstaticnames[i]; + int i = needed->ns_size++; + needed->nonstaticnames = (char**)box_realloc(needed->nonstaticnames, (i+1)*sizeof(char*)); + needed->nonstaticnames[i] = nsname; + return needed->nonstaticnames[i]; +} void setNeededLibs(library_t* lib, int n, ...) { diff --git a/src/libtools/decopcode.c b/src/libtools/decopcode.c index 0d21c8a8e..c81b88fea 100644 --- a/src/libtools/decopcode.c +++ b/src/libtools/decopcode.c @@ -1,6 +1,10 @@ // SPDX-License-Identifier: MIT #include #include +#if defined(__aarch64__) +#include +#include +#endif #include "debug.h" #include "x64emu.h" @@ -382,8 +386,21 @@ int decode_opcode(uintptr_t rip, int is32bits) return 0; } -int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits) +int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits, void* uctx) { - // TODO, on ARM64, RiSCV and LoongArch, it would be easier to analyse the opcode at the native IP instead, as opcode that write to memory are more limited in quantity + #if defined(__aarch64__) + if(uctx) { + struct _aarch64_ctx* ff = (struct _aarch64_ctx*)((ucontext_t*)uctx)->uc_mcontext.__reserved; + while(ff->magic && ff->size && ff->magic!=ESR_MAGIC) + ff = (struct _aarch64_ctx*)((uintptr_t)ff + ff->size); + if(ff->magic==ESR_MAGIC) { + uint64_t esr = ((struct esr_context*)ff)->esr; + if(((esr>>26)==0x24) && !(esr&(1<<8))) + // Data abort from EL0 with WnR set, not a cache maintenance operation (bit 8) + return(esr&(1<<6))?1:0; + } + } + #endif + // TODO, on RiSCV and LoongArch, it would be easier to analyse the opcode at the native IP instead, as opcode that write to memory are more limited in quantity return (decode_opcode(rip, is32bits)&OPCODE_WRITE)?1:0; } diff --git a/src/libtools/libc_net32.c b/src/libtools/libc_net32.c index e2017ce40..aac38a317 100644 --- a/src/libtools/libc_net32.c +++ b/src/libtools/libc_net32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/libtools/libdl.c b/src/libtools/libdl.c index fe8062130..c4c8147be 100644 --- a/src/libtools/libdl.c +++ b/src/libtools/libdl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/libtools/myalign64_32.c b/src/libtools/myalign64_32.c index d2eac77fd..871022f8e 100755 --- a/src/libtools/myalign64_32.c +++ b/src/libtools/myalign64_32.c @@ -129,12 +129,12 @@ struct native_statvfs { unsigned long int f_bsize; unsigned long int f_frsize; #ifndef ANDROID - __fsblkcnt64_t f_blocks; - __fsblkcnt64_t f_bfree; - __fsblkcnt64_t f_bavail; - __fsfilcnt64_t f_files; - __fsfilcnt64_t f_ffree; - __fsfilcnt64_t f_favail; + fsblkcnt_t f_blocks; + fsblkcnt_t f_bfree; + fsblkcnt_t f_bavail; + fsfilcnt_t f_files; + fsfilcnt_t f_ffree; + fsfilcnt_t f_favail; #else fsblkcnt_t f_blocks; fsblkcnt_t f_bfree; diff --git a/src/libtools/obstack.c b/src/libtools/obstack.c index 19a9a9999..4b40fee61 100644 --- a/src/libtools/obstack.c +++ b/src/libtools/obstack.c @@ -1,7 +1,4 @@ // SPDX-License-Identifier: MIT -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/libtools/signal32.c b/src/libtools/signal32.c index 8c8278999..78314e2ed 100644 --- a/src/libtools/signal32.c +++ b/src/libtools/signal32.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -33,29 +32,11 @@ #include "emu/x87emu_private.h" #include "custommem.h" #include "bridge.h" +#include "sigtools.h" #ifdef DYNAREC #include "dynablock.h" #include "../dynarec/dynablock_private.h" #include "dynarec_native.h" -#if defined(ARM64) -#include "dynarec/arm64/arm64_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.regs[X] -#define CONTEXT_PC(P) P->uc_mcontext.pc -#elif defined(LA64) -#include "dynarec/la64/la64_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.__gregs[X] -#define CONTEXT_PC(P) P->uc_mcontext.__pc; -#elif defined(RV64) -#include "dynarec/rv64/rv64_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.__gregs[X] -#define CONTEXT_PC(P) P->uc_mcontext.__gregs[REG_PC] -#elif defined(PPC64LE) -#include "dynarec/ppc64le/ppc64le_mapping.h" -#define CONTEXT_REG(P, X) P->uc_mcontext.gp_regs[X] -#define CONTEXT_PC(P) P->uc_mcontext.gp_regs[PT_NIP] -#else -#error Unsupported Architecture -#endif //arch #endif @@ -485,7 +466,6 @@ void convert_siginfo_to_32(void* d, void* s, int sig) void relockMutex(int locks); int unlockMutex(); -int write_opcode(uintptr_t rip, uintptr_t native_ip, int is32bits); #define is_memprot_locked (1<<1) #define is_dyndump_locked (1<<8) int my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db) @@ -638,7 +618,7 @@ int my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, sigin } else { sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14; sigcontext->uc_mcontext.gregs[I386_ERR] = 4|((sysmapped && !(real_prot&PROT_READ))?0:1); - if(write_opcode(sigcontext->uc_mcontext.gregs[I386_EIP], (uintptr_t)pc, 1)) + if(write_opcode(sigcontext->uc_mcontext.gregs[I386_EIP], (uintptr_t)pc, 1, ucntx)) sigcontext->uc_mcontext.gregs[I386_ERR] |= 2; } if(info->si_code == SEGV_ACCERR && old_code) diff --git a/src/libtools/signals.c b/src/libtools/signals.c index ababbda5f..8d7271632 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -511,7 +510,7 @@ int my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigin } else { sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; sigcontext->uc_mcontext.gregs[X64_ERR] = 4|((sysmapped && !(real_prot&PROT_READ))?0:1); - if(write_opcode(sigcontext->uc_mcontext.gregs[X64_RIP], (uintptr_t)pc, (R_CS==0x23))) + if(write_opcode(sigcontext->uc_mcontext.gregs[X64_RIP], (uintptr_t)pc, (R_CS==0x23), ucntx)) sigcontext->uc_mcontext.gregs[X64_ERR] |= 2; } if(info->si_code == SEGV_ACCERR && old_code) @@ -622,6 +621,8 @@ int my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigin emu->eflags.x64 = old_eflags; if(memcmp(sigcontext, &sigcontext_copy, sizeof(x64_ucontext_t))) { + fpu_xrstor_mask(emu, xstate, 0, 0b111); + emu->df = d_none; #if defined(DYNAREC) if(db || emu->jmpbuf) mctx2emu(emu, &sigcontext->uc_mcontext); @@ -882,6 +883,9 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) void * pc = NULL; // unknow arch... void* fpsimd = NULL; #warning Unhandled architecture +#endif +#ifndef PRINT_OPCODE +#define PRINT_OPCODE(C, A) "???" #endif dynablock_t* db = NULL; int db_searched = 0; @@ -909,9 +913,9 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) old_pc_i = 0; uint8_t* x64 = (uint8_t*)x64pc; if(db) - printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x (addr=%p, db=%p, x64pc=%p[%02hhX %02hhX %02hhX %02hhX %02hhX])\n", pc, *(uint32_t*)pc, addr, db, x64pc, x64[0], x64[1], x64[2], x64[3], x64[4], x64[5]); + printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x(%s) (addr=%p, db=%p, x64pc=%p[%02hhX %02hhX %02hhX %02hhX %02hhX])\n", pc, *(uint32_t*)pc, PRINT_OPCODE(*(uint32_t*)pc, (uintptr_t)pc), addr, db, x64pc, x64[0], x64[1], x64[2], x64[3], x64[4], x64[5]); else - printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x (addr=%p)\n", pc, *(uint32_t*)pc, addr); + printf_log(LOG_INFO, "Special unaligned case fixed @%p, opcode=%08x(%s) (addr=%p)\n", pc, *(uint32_t*)pc, PRINT_OPCODE(*(uint32_t*)pc, (uintptr_t)pc), addr); } } return; @@ -1007,27 +1011,20 @@ else dynarec_log(LOG_INFO, "SIGILL at %p/%p for Dynablock (%p, x64addr=%p) with // access error, unprotect the block (and mark them dirty) CheckHotPage((uintptr_t)addr, prot); unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected + int autosmc = 0; + if(db) { + autosmc = (addr >= db->x64_addr && addr < (db->x64_addr + db->x64_size)) + || (!BOX64ENV(dynarec_dirty) && ALIGN_DOWN((uintptr_t)addr) == ALIGN_DOWN((uintptr_t)db->x64_addr) && !is_addr_autosmc(x64pc)); + } int db_need_test = (db && !BOX64ENV(dynarec_dirty))?getNeedTest((uintptr_t)db->x64_addr):0; - if(db && ((addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) || db_need_test)) { + if(db && (autosmc || db_need_test)) { emu = getEmuSignal(emu, p, db); // dynablock got auto-dirty! need to get out of it!!! - uintptr_t x64pc = getX64Address(db, (uintptr_t)pc); copyUCTXreg2Emu(emu, p, db, x64pc); adjustregs(emu, pc); if(db && db->arch_size) ARCH_ADJUST(db, emu, p, x64pc); - int autosmc = (addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)); - if(autosmc && BOX64ENV(dynarec_dirty)) { - // check if current block should be cut there - int inst = getX64AddressInst(db, (uintptr_t)pc); - // is it the last instruction - uintptr_t next = getX64InstAddress(db, inst+1); - if(next!=(uintptr_t)-1LL) { - // there is a next, so lets mark the address and dirty the block - mark_db_autosmc(db, x64pc); - } - - } + if (autosmc) mark_db_autosmc(db, x64pc); dynarec_log(LOG_INFO, "Dynablock (%p, x64addr=%p, need_test=%d/%d/%d) %s, getting out at %p (%p)!\n", db, db->x64_addr, db_need_test, db->dirty, db->always_test, autosmc?"Auto-SMC":"unprotected", (void*)R_RIP, (void*)addr); //relockMutex(Locks); unlock_signal(); diff --git a/src/libtools/sigtools.c b/src/libtools/sigtools.c index 612b22348..c7a9cc63a 100644 --- a/src/libtools/sigtools.c +++ b/src/libtools/sigtools.c @@ -131,8 +131,8 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, // consider it a genuine SIGBUS, for example: store to a shared file mapping past the end of the file after a truncation #define CHECK_ALIGNED(addr, size) if((((uintptr_t)(addr)) & ((size)-1)) == 0) return 0; //printf_log(LOG_INFO, "Checking SIGBUS special cases with pc=%p, opcode=%x, fpsimd=%p\n", pc, opcode, fpsimd); - if((opcode&0b10111111110000000000000000000000)==0b10111001000000000000000000000000) { - // this is STR + if((opcode&0b00111111110000000000000000000000)==0b00111001000000000000000000000000) { + // this is STR(H/B) int scale = (opcode>>30)&3; int val = opcode&31; int dest = (opcode>>5)&31; @@ -141,7 +141,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(scale==3 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; @@ -151,8 +151,8 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b10111111111000000000110000000000) == 0b10111000000000000000000000000000) { - // this is a STUR that SIGBUS if accessing unaligned device memory + if((opcode&0b00111111111000000000110000000000) == 0b00111000000000000000000000000000) { + // this is a STUR(H/B) that SIGBUS if accessing unaligned device memory int size = 1<<((opcode>>30)&3); int val = opcode&31; int dest = (opcode>>5)&31; @@ -162,7 +162,29 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); - uint64_t value = p->uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; + if(size==8 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<2; ++i) + ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; + } else + for(int i=0; i>(i*8))&0xff; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } + if((opcode&0b00111111111000000000110000000000) == 0b00011001000000000000000000000000) { + // this is a STLUR(H/B) that SIGBUS if accessing unaligned device memory + int size = 1<<((opcode>>30)&3); + int val = opcode&31; + int dest = (opcode>>5)&31; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, size); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); // regen dynablock without this lrcpc opcode + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(size==8 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; @@ -199,7 +221,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, return 1; } if((opcode&0b00111111011000000000110000000000)==0b00111100000000000000000000000000) { - // this is VSTRU + // this is VSTUR int scale = (opcode>>30)&3; if((opcode>>23)&1) scale+=4; @@ -225,6 +247,34 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } + if((opcode&0b00111111011000000000110000000000)==0b00011101000000000000100000000000) { + // this is VSTLUR + int scale = (opcode>>30)&3; + if((opcode>>23)&1) + scale+=4; + if(scale>4) + return 0; + if(!fpsimd) + return 0; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + int val = opcode&31; + int dest = (opcode>>5)&31; + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, 1<vregs[val]; + if(scale>2 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<(1<<(scale-2)); ++i) + ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; + } else + for(int i=0; i<(1<>(i*8))&0xff; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } if((opcode&0b00111111010000000000000000000000)==0b00111101010000000000000000000000) { // this is VLDR int scale = (opcode>>30)&3; @@ -253,7 +303,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, return 1; } if((opcode&0b00111111011000000000110000000000)==0b00111100010000000000000000000000) { - // this is VLDRU + // this is VLDUR int scale = (opcode>>30)&3; if((opcode>>23)&1) scale+=4; @@ -280,6 +330,35 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, p->uc_mcontext.pc+=4; // go to next opcode return 1; } + if((opcode&0b00111111011000000000110000000000)==0b00011101010000000000100000000000) { + // this is VLDAPUR + int scale = (opcode>>30)&3; + if((opcode>>23)&1) + scale+=4; + if(scale>4) + return 0; + if(!fpsimd) + return 0; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + int val = opcode&31; + int dest = (opcode>>5)&31; + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, 1<2 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<(1<<(scale-2)); ++i) + value |= ((__uint128_t)(((volatile uint32_t*)addr)[i]))<<(i*32); + } else + for(int i=0; i<(1<vregs[val] = value; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } if((opcode&0b10111111110000000000000000000000)==0b10111001010000000000000000000000) { // this is LDR int scale = (opcode>>30)&3; @@ -297,7 +376,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, } else for(int i=0; i<(1<uc_mcontext.regs[val] = value; + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } @@ -319,28 +398,54 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, } else for(int i=0; iuc_mcontext.regs[val] = value; + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b11111111110000000000000000000000)==0b01111001000000000000000000000000) { - // this is STRH - int scale = (opcode>>30)&3; + if((opcode&0b10111111111000000000110000000000) == 0b10011001010000000000000000000000) { + // this is a LDAPUR + int size = 1<<((opcode>>30)&3); int val = opcode&31; int dest = (opcode>>5)&31; - uint64_t offset = (opcode>>10)&0b111111111111; - offset<<=scale; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); - CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val]; - for(int i=0; i<(1<>(i*8))&0xff; + CHECK_ALIGNED(addr, size); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); + uint64_t value = 0; + if(size==8 && (((uintptr_t)addr)&3)==0) { + for(int i=0; i<2; ++i) + value |= ((uint64_t)((volatile uint32_t*)addr)[i]) << (i*32); + } else + for(int i=0; iuc_mcontext.regs[val] = value; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } + if((opcode&0b11111111111000000000110000000000) == 0b10011001100000000000000000000000) { + // this is a LDAPURSW + int size = 1<<((opcode>>30)&3); + int val = opcode&31; + int dest = (opcode>>5)&31; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, size); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); + int32_t value = 0; + for(int i=0; iuc_mcontext.regs[val] = (int64_t)value; p->uc_mcontext.pc+=4; // go to next opcode return 1; } - if((opcode&0b11111111111000000000110000000000)==0b01111000000000000000000000000000) { - // this is STURH + if((opcode&0b11111111111000000000110000000000) == 0b01011001010000000000000000000000) { + // this is a LDAPURH int val = opcode&31; int dest = (opcode>>5)&31; int64_t offset = (opcode>>12)&0b111111111; @@ -349,9 +454,32 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 2); - uint64_t value = p->uc_mcontext.regs[val]; + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); + uint16_t value = 0; for(int i=0; i<2; ++i) - addr[i] = (value>>(i*8))&0xff; + value |= ((uint16_t)addr[i]) << (i*8); + if(val!=xZR) p->uc_mcontext.regs[val] = value; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } + if((opcode&0b11111111101000000000110000000000) == 0b01011001100000000000000000000000) { + // this is a LDAPURSH + int val = opcode&31; + int dest = (opcode>>5)&31; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[dest] + offset); + if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); + CHECK_ALIGNED(addr, 2); + if(arch_lrcpc(db, x64pc)) mark_db_lrcpc(db, x64pc); + int16_t value = 0; + for(int i=0; i<2; ++i) + value |= ((int16_t)addr[i]) << (i*8); + if(val!=xZR) { + p->uc_mcontext.regs[val] = (int64_t)value; + if((opcode>>22)&1) p->uc_mcontext.regs[val]&=0xffffffffULL; + } p->uc_mcontext.pc+=4; // go to next opcode return 1; } @@ -365,11 +493,11 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, int S = (opcode>>12)&1; if(option!=0b011) return 0; // only LSL is supported - uint64_t offset = p->uc_mcontext.regs[dest2]<uc_mcontext.regs[dest2])<uc_mcontext.regs[dest] + offset); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; for(int i=0; i<(1<>(i*8))&0xff; p->uc_mcontext.pc+=4; // go to next opcode @@ -389,10 +517,10 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, if(is32bits) addr = addr&0xffffffff; CHECK_ALIGNED(addr, 1<uc_mcontext.regs[val1]; - ((volatile uint32_t*)addr)[1] = p->uc_mcontext.regs[val2]; + ((volatile uint32_t*)addr)[0] = (val1==xZR)?0:p->uc_mcontext.regs[val1]; + ((volatile uint32_t*)addr)[1] = (val2==xZR)?0:p->uc_mcontext.regs[val2]; } else { - __uint128_t value = ((__uint128_t)p->uc_mcontext.regs[val2])<<64 | p->uc_mcontext.regs[val1]; + __uint128_t value = ((__uint128_t)((val2==xZR)?0:p->uc_mcontext.regs[val2]))<<64 | ((val1==xZR)?0:p->uc_mcontext.regs[val1]); for(int i=0; i<(1<>(i*8))&0xff; } @@ -462,7 +590,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, } else for(int i=0; iuc_mcontext.regs[val] = value; + if(val!=xZR) p->uc_mcontext.regs[val] = value; p->uc_mcontext.regs[dest] += offset; p->uc_mcontext.pc+=4; // go to next opcode return 1; @@ -478,7 +606,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd, volatile uint8_t* addr = (void*)(p->uc_mcontext.regs[src]); if(is32bits) addr = (uint8_t*)(((uintptr_t)addr)&0xffffffff); CHECK_ALIGNED(addr, size); - uint64_t value = p->uc_mcontext.regs[val]; + uint64_t value = (val==xZR)?0:p->uc_mcontext.regs[val]; if(size==8 && (((uintptr_t)addr)&3)==0) { for(int i=0; i<2; ++i) ((volatile uint32_t*)addr)[i] = (value>>(i*32))&0xffffffff; diff --git a/src/libtools/syscall_user_dispatch.c b/src/libtools/syscall_user_dispatch.c index 68c6efc41..83675104b 100644 --- a/src/libtools/syscall_user_dispatch.c +++ b/src/libtools/syscall_user_dispatch.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/libtools/threads.c b/src/libtools/threads.c index a5eb14819..8b44a8478 100644 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT // __USE_UNIX98 is needed for sttype / gettype definition #define __USE_UNIX98 -#define _GNU_SOURCE #include #include #include @@ -278,7 +277,7 @@ x64emu_t* thread_get_emu(void) int stacksize = 256*1024; void* stack = NULL; if(box64_is32bits) - stack = mmap64(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); + stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); else stack = InternalMmap(NULL, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); if(stack!=MAP_FAILED && !box64_quit) // to avoid marking memory when box64 is quitting diff --git a/src/libtools/threads32.c b/src/libtools/threads32.c index a5220cfc4..924fed3d5 100755 --- a/src/libtools/threads32.c +++ b/src/libtools/threads32.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT // __USE_UNIX98 is needed for sttype / gettype definition #define __USE_UNIX98 -#define _GNU_SOURCE #include #include #include @@ -273,7 +272,7 @@ void* my32_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** p { int stacksize = (ssize)?ssize:(2*1024*1024); //default stack size is 2Mo //void* stack = malloc(stacksize); - void* stack = mmap64(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); + void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); if(stack==MAP_FAILED) return NULL; emuthread_t *et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t)); diff --git a/src/libtools/vulkanoverlay.c b/src/libtools/vulkanoverlay.c index e67201024..3b5830bd3 100644 --- a/src/libtools/vulkanoverlay.c +++ b/src/libtools/vulkanoverlay.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/mallochook.c b/src/mallochook.c index 80f7696b1..ad8d28646 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/os/hostext_common.c b/src/os/hostext_common.c index 723fd724f..7ddac4423 100644 --- a/src/os/hostext_common.c +++ b/src/os/hostext_common.c @@ -22,6 +22,10 @@ void PrintHostCpuFeatures(void) printf_log_prefix(0, LOG_INFO, " USCAT"); if(cpuext.flagm) printf_log_prefix(0, LOG_INFO, " FLAGM"); + if(cpuext.lrcpc) + printf_log_prefix(0, LOG_INFO, " LRCPC"); + if(cpuext.lrcpc2) + printf_log_prefix(0, LOG_INFO, " LRCPC2"); if(cpuext.flagm2) printf_log_prefix(0, LOG_INFO, " FLAGM2"); if(cpuext.frintts) @@ -30,6 +34,8 @@ void PrintHostCpuFeatures(void) printf_log_prefix(0, LOG_INFO, " AFP"); if(cpuext.rndr) printf_log_prefix(0, LOG_INFO, " RNDR"); + if(cpuext.lrcpc3) + printf_log_prefix(0, LOG_INFO, " LRCPC3"); printf_log_prefix(0, LOG_INFO, "\n"); #elif defined(LA64) printf_log(LOG_INFO, "Dynarec for LoongArch with extension LSX"); diff --git a/src/os/hostext_linux.c b/src/os/hostext_linux.c index 6aed44c0a..95423b796 100644 --- a/src/os/hostext_linux.c +++ b/src/os/hostext_linux.c @@ -228,6 +228,14 @@ int DetectHostCpuFeatures(void) if(hwcap&HWCAP_FLAGM) cpuext.flagm = 1; #endif + #ifdef HWCAP_LRCPC + if(hwcap&HWCAP_LRCPC) + cpuext.lrcpc = 1; + #endif + #ifdef HWCAP_ILRCPC + if(hwcap&HWCAP_ILRCPC) + cpuext.lrcpc2 = 1; + #endif unsigned long hwcap2 = real_getauxval(AT_HWCAP2); #ifdef HWCAP2_FLAGM2 if(hwcap2&HWCAP2_FLAGM2) @@ -245,6 +253,10 @@ int DetectHostCpuFeatures(void) if(hwcap2&HWCAP2_RNG) cpuext.rndr = 1; #endif + #ifdef HWCAP2_LRCPC3 + if(hwcap2&HWCAP2_LRCPC3) + cpuext.lrcpc3 = 1; + #endif if (p) { p = strtok(p, ","); while (p) { @@ -256,10 +268,13 @@ int DetectHostCpuFeatures(void) if (!strcasecmp(p, "sha2")) cpuext.sha2 = 0; if (!strcasecmp(p, "uscat")) cpuext.uscat = 0; if (!strcasecmp(p, "flagm")) cpuext.flagm = 0; + if (!strcasecmp(p, "lrcpc")) cpuext.lrcpc = 0; + if (!strcasecmp(p, "lrcpc2")) cpuext.lrcpc2 = 0; if (!strcasecmp(p, "flagm2")) cpuext.flagm2 = 0; if (!strcasecmp(p, "frintts")) cpuext.frintts = 0; if (!strcasecmp(p, "afp")) cpuext.afp = 0; if (!strcasecmp(p, "rndr")) cpuext.rndr = 0; + if (!strcasecmp(p, "lrcpc3")) cpuext.lrcpc3 = 0; p = strtok(NULL, ","); } } @@ -322,6 +337,14 @@ int DetectHostCpuFeatures(void) p = strtok(NULL, ","); } } + if (!cpuext.vector) { + cpuext.vlen = 0; + cpuext.zvkned = 0; + cpuext.zvknha = 0; + cpuext.zvknhb = 0; + cpuext.zvbb = 0; + cpuext.zvfh = 0; + } } #elif defined(PPC64LE) unsigned long hwcap = real_getauxval(AT_HWCAP); diff --git a/src/os/my_cpuid.c b/src/os/my_cpuid.c index 8ebcde97a..be1e7d64f 100644 --- a/src/os/my_cpuid.c +++ b/src/os/my_cpuid.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include diff --git a/src/os/os_linux.c b/src/os/os_linux.c index 141ba0c90..948d723a3 100644 --- a/src/os/os_linux.c +++ b/src/os/os_linux.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/os/sysinfo.c b/src/os/sysinfo.c index 9daa7ce2d..db78a126e 100644 --- a/src/os/sysinfo.c +++ b/src/os/sysinfo.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/test.c b/src/test.c index 45d0b9e5a..f308225f5 100644 --- a/src/test.c +++ b/src/test.c @@ -613,6 +613,7 @@ static int runSingleTest(const char* filepath, const char* include_path) x64emu_t* emu = NewX64Emu(my_context, my_context->ep, (uintptr_t)my_context->stack, my_context->stacksz, 0); + thread_set_emu(emu); bool have_mmregs = false; for (int i = 0; i < 8; ++i) { diff --git a/src/tools/bridge.c b/src/tools/bridge.c index 3f9324fec..b3aced3e1 100644 --- a/src/tools/bridge.c +++ b/src/tools/bridge.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/tools/cpumask.c b/src/tools/cpumask.c index 7db40e396..62f9afa4d 100644 --- a/src/tools/cpumask.c +++ b/src/tools/cpumask.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT #ifndef _WIN32 -#define _GNU_SOURCE #include #endif #include diff --git a/src/tools/env.c b/src/tools/env.c index 37e3caa4f..5c710f51d 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -238,6 +238,7 @@ static void applyCustomRules() SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 0); SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 2); SET_BOX64ENV_IF_EMPTY(dynarec_strongmem, 2); + SET_BOX64ENV_IF_EMPTY(dynarec_callret, 3); } else if (!strcasecmp(box64env.profile, "safe")) { SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 0); SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 2); @@ -866,7 +867,7 @@ void RecordEnvMappings(uintptr_t addr, size_t length, int fd) if(new_mapping) { // First time we see this file if (box64_wine && BOX64ENV(unityplayer)) DetectUnityPlayer(lowercase_filename+1); - if (box64_wine && !box64_is32bits && BOX64ENV(dynarec_volatile_metadata)) ParseVolatileMetadata(fullname, (void*)addr); + if (box64_wine && !box64_is32bits && BOX64ENV(dynarec_volatile_metadata) && (getProtection(addr)&PROT_READ)) ParseVolatileMetadata(fullname, (void*)addr); #if defined(DYNAREC) && !defined(WIN32) int dynacache = box64env.dynacache; if(mapping->env && mapping->env->is_dynacache_overridden) diff --git a/src/tools/fileutils.c b/src/tools/fileutils.c index 6e4487758..9093e6978 100644 --- a/src/tools/fileutils.c +++ b/src/tools/fileutils.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _FILE_OFFSET_BITS 64 #include #include #include diff --git a/src/tools/gtkclass.c b/src/tools/gtkclass.c index ef3fca573..8ebe256fd 100644 --- a/src/tools/gtkclass.c +++ b/src/tools/gtkclass.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/tools/wine_tools.c b/src/tools/wine_tools.c index 28eb436b4..e59afb0fd 100644 --- a/src/tools/wine_tools.c +++ b/src/tools/wine_tools.c @@ -25,7 +25,7 @@ typedef struct wine_prereserve_32_s #include "box32.h" #endif // only the prereseve argument is reserved, not the other zone that wine-preloader reserve -static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00008000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}}; +static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00010000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}}; int wine_preloaded = 0; diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt index c8525f16c..729135dc4 100644 --- a/src/wrapped/generated/functions_list.txt +++ b/src/wrapped/generated/functions_list.txt @@ -3925,6 +3925,7 @@ #() pFppuiipuuii #() pFppuuLLuppp #() pFpppiiiiiii +#() pFpppppiiiii #() pFpppppppppp #() pFbuuuWWWCCi #() iWEpuipupppp @@ -4427,6 +4428,7 @@ wrappedcrypto3: - EVP_MD_do_all_provided - iFppp: - ASN1_i2d_bio + - CRYPTO_set_mem_functions - iFppV: - BIO_printf - pFppp: @@ -7741,6 +7743,8 @@ wrappedwaylandclient: - wl_log_set_handler_client - iFppp: - wl_proxy_add_listener +- iFpppp: + - wl_proxy_add_dispatcher wrappedwaylandcursor: wrappedwaylandegl: wrappedxinerama: diff --git a/src/wrapped/generated/wrappedcrypto3types.h b/src/wrapped/generated/wrappedcrypto3types.h index 05ea31e67..8eb7bd031 100644 --- a/src/wrapped/generated/wrappedcrypto3types.h +++ b/src/wrapped/generated/wrappedcrypto3types.h @@ -62,6 +62,7 @@ typedef void* (*pFpppppppp_t)(void*, void*, void*, void*, void*, void*, void*, v GO(UI_method_set_writer, iFpp_t) \ GO(EVP_MD_do_all_provided, vFppp_t) \ GO(ASN1_i2d_bio, iFppp_t) \ + GO(CRYPTO_set_mem_functions, iFppp_t) \ GO(BIO_printf, iFppV_t) \ GO(OPENSSL_sk_deep_copy, pFppp_t) \ GO(OSSL_PARAM_construct_int, pFppp_t) \ diff --git a/src/wrapped/generated/wrappedwaylandclienttypes.h b/src/wrapped/generated/wrappedwaylandclienttypes.h index 0b22de652..5fc4a674f 100644 --- a/src/wrapped/generated/wrappedwaylandclienttypes.h +++ b/src/wrapped/generated/wrappedwaylandclienttypes.h @@ -14,9 +14,11 @@ typedef void (*vFp_t)(void*); typedef int32_t (*iFppp_t)(void*, void*, void*); +typedef int32_t (*iFpppp_t)(void*, void*, void*, void*); #define SUPER() ADDED_FUNCTIONS() \ GO(wl_log_set_handler_client, vFp_t) \ - GO(wl_proxy_add_listener, iFppp_t) + GO(wl_proxy_add_listener, iFppp_t) \ + GO(wl_proxy_add_dispatcher, iFpppp_t) #endif // __wrappedwaylandclientTYPES_H_ diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c index bf7313827..a98662071 100644 --- a/src/wrapped/generated/wrapper.c +++ b/src/wrapped/generated/wrapper.c @@ -3953,6 +3953,7 @@ typedef void* (*pFppippLLLip_t)(void*, void*, int32_t, void*, void*, uintptr_t, typedef void* (*pFppuiipuuii_t)(void*, void*, uint32_t, int32_t, int32_t, void*, uint32_t, uint32_t, int32_t, int32_t); typedef void* (*pFppuuLLuppp_t)(void*, void*, uint32_t, uint32_t, uintptr_t, uintptr_t, uint32_t, void*, void*, void*); typedef void* (*pFpppiiiiiii_t)(void*, void*, void*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); +typedef void* (*pFpppppiiiii_t)(void*, void*, void*, void*, void*, int32_t, int32_t, int32_t, int32_t, int32_t); typedef void* (*pFpppppppppp_t)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*); typedef void* (*pFbuuuWWWCCi_t)(void*, uint32_t, uint32_t, uint32_t, uint16_t, uint16_t, uint16_t, uint8_t, uint8_t, int32_t); typedef int32_t (*iWEpuipupppp_t)(x64emu_t*, void*, uint32_t, int32_t, void*, uint32_t, void*, void*, void*, void*); @@ -8241,6 +8242,7 @@ void pFppippLLLip(x64emu_t *emu, uintptr_t fcn) { pFppippLLLip_t fn = (pFppippLL void pFppuiipuuii(x64emu_t *emu, uintptr_t fcn) { pFppuiipuuii_t fn = (pFppuiipuuii_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } void pFppuuLLuppp(x64emu_t *emu, uintptr_t fcn) { pFppuuLLuppp_t fn = (pFppuuLLuppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } void pFpppiiiiiii(x64emu_t *emu, uintptr_t fcn) { pFpppiiiiiii_t fn = (pFpppiiiiiii_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } +void pFpppppiiiii(x64emu_t *emu, uintptr_t fcn) { pFpppppiiiii_t fn = (pFpppppiiiii_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); } void pFpppppppppp(x64emu_t *emu, uintptr_t fcn) { pFpppppppppp_t fn = (pFpppppppppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); } void pFbuuuWWWCCi(x64emu_t *emu, uintptr_t fcn) { pFbuuuWWWCCi_t fn = (pFbuuuWWWCCi_t)fcn; void *aligned_xcb = align_xcb_connection((void*)R_RDI); R_RAX=(uintptr_t)fn(aligned_xcb, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint16_t)R_R8, (uint16_t)R_R9, *(uint16_t*)(R_RSP + 8), *(uint8_t*)(R_RSP + 16), *(uint8_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32)); unalign_xcb_connection(aligned_xcb, (void*)R_RDI); } void iWEpuipupppp(x64emu_t *emu, uintptr_t fcn) { iWEpuipupppp_t fn = (iWEpuipupppp_t)fcn; R_RAX=(int)fn(emu, (void*)R_RCX, (uint32_t)R_RDX, (int32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72)); } diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h index 0d6c831d3..180a881a5 100644 --- a/src/wrapped/generated/wrapper.h +++ b/src/wrapped/generated/wrapper.h @@ -3963,6 +3963,7 @@ void pFppippLLLip(x64emu_t *emu, uintptr_t fnc); void pFppuiipuuii(x64emu_t *emu, uintptr_t fnc); void pFppuuLLuppp(x64emu_t *emu, uintptr_t fnc); void pFpppiiiiiii(x64emu_t *emu, uintptr_t fnc); +void pFpppppiiiii(x64emu_t *emu, uintptr_t fnc); void pFpppppppppp(x64emu_t *emu, uintptr_t fnc); void pFbuuuWWWCCi(x64emu_t *emu, uintptr_t fnc); void iWEpuipupppp(x64emu_t *emu, uintptr_t fnc); diff --git a/src/wrapped/wrappedalure.c b/src/wrapped/wrappedalure.c index 5d5852779..7217db8da 100644 --- a/src/wrapped/wrappedalure.c +++ b/src/wrapped/wrappedalure.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedalut.c b/src/wrapped/wrappedalut.c index 418b08380..46636d404 100644 --- a/src/wrapped/wrappedalut.c +++ b/src/wrapped/wrappedalut.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedandroidshmem.c b/src/wrapped/wrappedandroidshmem.c index 50ad62a7f..f3facfa0f 100755 --- a/src/wrapped/wrappedandroidshmem.c +++ b/src/wrapped/wrappedandroidshmem.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedandroidsupport.c b/src/wrapped/wrappedandroidsupport.c index 82f1eb638..95dd71882 100644 --- a/src/wrapped/wrappedandroidsupport.c +++ b/src/wrapped/wrappedandroidsupport.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedanl.c b/src/wrapped/wrappedanl.c index 74f869afb..88655e226 100644 --- a/src/wrapped/wrappedanl.c +++ b/src/wrapped/wrappedanl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedatk.c b/src/wrapped/wrappedatk.c index 156cbe539..7581d7454 100644 --- a/src/wrapped/wrappedatk.c +++ b/src/wrapped/wrappedatk.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedatkbridge.c b/src/wrapped/wrappedatkbridge.c index 7049d60b4..1e17a59d6 100644 --- a/src/wrapped/wrappedatkbridge.c +++ b/src/wrapped/wrappedatkbridge.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedatomic.c b/src/wrapped/wrappedatomic.c index d1a3b3c80..a7e8de798 100644 --- a/src/wrapped/wrappedatomic.c +++ b/src/wrapped/wrappedatomic.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedatspi.c b/src/wrapped/wrappedatspi.c index b50f57ee0..4b80a0c36 100644 --- a/src/wrapped/wrappedatspi.c +++ b/src/wrapped/wrappedatspi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedavahiclient.c b/src/wrapped/wrappedavahiclient.c index a4b1c05e3..5433a1ad2 100644 --- a/src/wrapped/wrappedavahiclient.c +++ b/src/wrapped/wrappedavahiclient.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedavahicommon.c b/src/wrapped/wrappedavahicommon.c index ac1a6706c..670e2cab4 100644 --- a/src/wrapped/wrappedavahicommon.c +++ b/src/wrapped/wrappedavahicommon.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedayatanaappindicator3.c b/src/wrapped/wrappedayatanaappindicator3.c index 9302834f8..5acebbb90 100644 --- a/src/wrapped/wrappedayatanaappindicator3.c +++ b/src/wrapped/wrappedayatanaappindicator3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedayatanaido3.c b/src/wrapped/wrappedayatanaido3.c index bf68467c0..5a433c55c 100644 --- a/src/wrapped/wrappedayatanaido3.c +++ b/src/wrapped/wrappedayatanaido3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedayatanaindicator3.c b/src/wrapped/wrappedayatanaindicator3.c index e3c64a021..d2e34048d 100644 --- a/src/wrapped/wrappedayatanaindicator3.c +++ b/src/wrapped/wrappedayatanaindicator3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedbrotlidec.c b/src/wrapped/wrappedbrotlidec.c index 91ec1c3da..dab1dd329 100644 --- a/src/wrapped/wrappedbrotlidec.c +++ b/src/wrapped/wrappedbrotlidec.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedbz2.c b/src/wrapped/wrappedbz2.c index 6824e8ff5..5a49d8c4a 100644 --- a/src/wrapped/wrappedbz2.c +++ b/src/wrapped/wrappedbz2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcairo.c b/src/wrapped/wrappedcairo.c index 78fa2dcbb..eaf417662 100644 --- a/src/wrapped/wrappedcairo.c +++ b/src/wrapped/wrappedcairo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcairogobject.c b/src/wrapped/wrappedcairogobject.c index fb77d935d..95c0a8585 100644 --- a/src/wrapped/wrappedcairogobject.c +++ b/src/wrapped/wrappedcairogobject.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcap.c b/src/wrapped/wrappedcap.c index f497c1186..0a5423c40 100644 --- a/src/wrapped/wrappedcap.c +++ b/src/wrapped/wrappedcap.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedcrypto.c b/src/wrapped/wrappedcrypto.c index eed765240..e9a1f82d6 100644 --- a/src/wrapped/wrappedcrypto.c +++ b/src/wrapped/wrappedcrypto.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedcrypto3.c b/src/wrapped/wrappedcrypto3.c index 419ad501a..109d591d4 100644 --- a/src/wrapped/wrappedcrypto3.c +++ b/src/wrapped/wrappedcrypto3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include @@ -628,6 +627,82 @@ static void* find_ECDH_KDF_Fct(void* fct) return NULL; } +// mem_malloc +#define GO(A) \ +static uintptr_t my3_mem_malloc_fct_##A = 0; \ +static void* my3_mem_malloc_##A(size_t a, void* b, int c) \ +{ \ + return (void*)RunFunctionFmt(my3_mem_malloc_fct_##A, "Lpi", a, b, c); \ +} +SUPER() +#undef GO +static void* find_mem_malloc_Fct(void* fct) +{ + if(!fct) return NULL; + void* p; + if((p = GetNativeFnc((uintptr_t)fct))) return p; + #define GO(A) if(my3_mem_malloc_fct_##A == (uintptr_t)fct) return my3_mem_malloc_##A; + SUPER() + #undef GO + #define GO(A) if(my3_mem_malloc_fct_##A == 0) {my3_mem_malloc_fct_##A = (uintptr_t)fct; return my3_mem_malloc_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for libcrypto mem_malloc callback\n"); + return NULL; +} +// mem_realloc +#define GO(A) \ +static uintptr_t my3_mem_realloc_fct_##A = 0; \ +static void* my3_mem_realloc_##A(void* a, size_t b, void* c, int d) \ +{ \ + return (void*)RunFunctionFmt(my3_mem_realloc_fct_##A, "pLpi", a, b, c, d); \ +} +SUPER() +#undef GO +static void* find_mem_realloc_Fct(void* fct) +{ + if(!fct) return NULL; + void* p; + if((p = GetNativeFnc((uintptr_t)fct))) return p; + #define GO(A) if(my3_mem_realloc_fct_##A == (uintptr_t)fct) return my3_mem_realloc_##A; + SUPER() + #undef GO + #define GO(A) if(my3_mem_realloc_fct_##A == 0) {my3_mem_realloc_fct_##A = (uintptr_t)fct; return my3_mem_realloc_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for libcrypto mem_realloc callback\n"); + return NULL; +} +// mem_free +#define GO(A) \ +static uintptr_t my3_mem_free_fct_##A = 0; \ +static void my3_mem_free_##A(void* a, void* b, int c) \ +{ \ + RunFunctionFmt(my3_mem_free_fct_##A, "ppi", a, b, c); \ +} +SUPER() +#undef GO +static void* find_mem_free_Fct(void* fct) +{ + if(!fct) return NULL; + void* p; + if((p = GetNativeFnc((uintptr_t)fct))) return p; + #define GO(A) if(my3_mem_free_fct_##A == (uintptr_t)fct) return my3_mem_free_##A; + SUPER() + #undef GO + #define GO(A) if(my3_mem_free_fct_##A == 0) {my3_mem_free_fct_##A = (uintptr_t)fct; return my3_mem_free_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for libcrypto mem_free callback\n"); + return NULL; +} + +EXPORT int my3_CRYPTO_set_mem_functions(x64emu_t* emu, void* m, void* r, void* f) +{ + (void)emu; + return my->CRYPTO_set_mem_functions(find_mem_malloc_Fct(m), find_mem_realloc_Fct(r), find_mem_free_Fct(f)); +} + EXPORT int my3_CRYPTO_get_ex_new_index(x64emu_t* emu, int idx, long argl, void* argp, void* new_func, void* dup_func, void* free_func) { (void)emu; diff --git a/src/wrapped/wrappedcrypto3_private.h b/src/wrapped/wrappedcrypto3_private.h index 89af41aee..31027348b 100644 --- a/src/wrapped/wrappedcrypto3_private.h +++ b/src/wrapped/wrappedcrypto3_private.h @@ -918,7 +918,7 @@ GOM(CRYPTO_set_locking_callback, vFEp) //GO(CRYPTO_set_mem_debug_functions, //GO(CRYPTO_set_mem_debug_options, //GO(CRYPTO_set_mem_ex_functions, -//GOM(CRYPTO_set_mem_functions, iFEppp) +GOM(CRYPTO_set_mem_functions, iFEppp) GO(CRYPTO_strdup, pFppi) //GO(CRYPTO_thread_id, //GO(CRYPTO_THREADID_cmp, @@ -2999,7 +2999,7 @@ GOM(PEM_X509_INFO_read_bio, pFEpppp) //GO(PKCS12_BAGS_new, //GO(PKCS12_certbag2x509, //GO(PKCS12_certbag2x509crl, -GO(PKCS12_create, pFppppp) +GO(PKCS12_create, pFpppppiiiii) //GO(PKCS12_decrypt_skey, GO(PKCS12_free, vFp) //GO(PKCS12_gen_mac, diff --git a/src/wrapped/wrappedcrypto_private.h b/src/wrapped/wrappedcrypto_private.h index fb37bb355..9f5d8cbf9 100644 --- a/src/wrapped/wrappedcrypto_private.h +++ b/src/wrapped/wrappedcrypto_private.h @@ -2861,7 +2861,7 @@ GO(PEM_write_bio_X509_REQ, iFpp) //GO(PKCS12_BAGS_new, //GO(PKCS12_certbag2x509, //GO(PKCS12_certbag2x509crl, -GO(PKCS12_create, pFppppp) +GO(PKCS12_create, pFpppppiiiii) //GO(PKCS12_decrypt_skey, GO(PKCS12_free, vFp) //GO(PKCS12_gen_mac, diff --git a/src/wrapped/wrappedcuda.c b/src/wrapped/wrappedcuda.c index 61e0e6a0e..92c1854ea 100644 --- a/src/wrapped/wrappedcuda.c +++ b/src/wrapped/wrappedcuda.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedcurl.c b/src/wrapped/wrappedcurl.c index fb4b3ffc1..c082b13d2 100644 --- a/src/wrapped/wrappedcurl.c +++ b/src/wrapped/wrappedcurl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedd3dadapter9.c b/src/wrapped/wrappedd3dadapter9.c index c868602ae..a20f1dd22 100644 --- a/src/wrapped/wrappedd3dadapter9.c +++ b/src/wrapped/wrappedd3dadapter9.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappeddbus.c b/src/wrapped/wrappeddbus.c index a000729e3..dd76acf22 100644 --- a/src/wrapped/wrappeddbus.c +++ b/src/wrapped/wrappeddbus.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappeddbusglib1.c b/src/wrapped/wrappeddbusglib1.c index cbfb00484..6c87824e9 100644 --- a/src/wrapped/wrappeddbusglib1.c +++ b/src/wrapped/wrappeddbusglib1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappeddbusmenuglib.c b/src/wrapped/wrappeddbusmenuglib.c index cca46cc59..0951ed0ab 100644 --- a/src/wrapped/wrappeddbusmenuglib.c +++ b/src/wrapped/wrappeddbusmenuglib.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappeddecor0.c b/src/wrapped/wrappeddecor0.c index e6bdb3d37..e38e50ae2 100644 --- a/src/wrapped/wrappeddecor0.c +++ b/src/wrapped/wrappeddecor0.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedevent21.c b/src/wrapped/wrappedevent21.c index a4f5037d0..fe569ce36 100644 --- a/src/wrapped/wrappedevent21.c +++ b/src/wrapped/wrappedevent21.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedexpat.c b/src/wrapped/wrappedexpat.c index 5ca18bb0b..c8be7b1bd 100644 --- a/src/wrapped/wrappedexpat.c +++ b/src/wrapped/wrappedexpat.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedfaudio.c b/src/wrapped/wrappedfaudio.c index a0a708957..23f321f17 100644 --- a/src/wrapped/wrappedfaudio.c +++ b/src/wrapped/wrappedfaudio.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedflac.c b/src/wrapped/wrappedflac.c index f531a1917..5faa1b63f 100644 --- a/src/wrapped/wrappedflac.c +++ b/src/wrapped/wrappedflac.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedfontconfig.c b/src/wrapped/wrappedfontconfig.c index cc237f75f..747cb4341 100644 --- a/src/wrapped/wrappedfontconfig.c +++ b/src/wrapped/wrappedfontconfig.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedfreebl3.c b/src/wrapped/wrappedfreebl3.c index b24216937..c8c12de66 100644 --- a/src/wrapped/wrappedfreebl3.c +++ b/src/wrapped/wrappedfreebl3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedfreetype.c b/src/wrapped/wrappedfreetype.c index 8fbc755eb..092fd6d7e 100644 --- a/src/wrapped/wrappedfreetype.c +++ b/src/wrapped/wrappedfreetype.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgbm.c b/src/wrapped/wrappedgbm.c index 02de742b9..ad2a6df96 100644 --- a/src/wrapped/wrappedgbm.c +++ b/src/wrapped/wrappedgbm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgconf2.c b/src/wrapped/wrappedgconf2.c index 2c1250c98..e8e4ee016 100644 --- a/src/wrapped/wrappedgconf2.c +++ b/src/wrapped/wrappedgconf2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgcrypt.c b/src/wrapped/wrappedgcrypt.c index 24d769429..dc3e3e7c3 100644 --- a/src/wrapped/wrappedgcrypt.c +++ b/src/wrapped/wrappedgcrypt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgdk3.c b/src/wrapped/wrappedgdk3.c index a9cf7c72b..7f6b85d14 100644 --- a/src/wrapped/wrappedgdk3.c +++ b/src/wrapped/wrappedgdk3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedgdkpixbuf2.c b/src/wrapped/wrappedgdkpixbuf2.c index d07e28911..6b7ca4f66 100644 --- a/src/wrapped/wrappedgdkpixbuf2.c +++ b/src/wrapped/wrappedgdkpixbuf2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgdkx112.c b/src/wrapped/wrappedgdkx112.c index 39a438239..a2fac3da4 100644 --- a/src/wrapped/wrappedgdkx112.c +++ b/src/wrapped/wrappedgdkx112.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgio2.c b/src/wrapped/wrappedgio2.c index 4e8cdf030..8710af15d 100644 --- a/src/wrapped/wrappedgio2.c +++ b/src/wrapped/wrappedgio2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedglesv2.c b/src/wrapped/wrappedglesv2.c index 025c96ab7..6a8f8758c 100644 --- a/src/wrapped/wrappedglesv2.c +++ b/src/wrapped/wrappedglesv2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedglib2.c b/src/wrapped/wrappedglib2.c index 11bfff627..b21a3c23b 100644 --- a/src/wrapped/wrappedglib2.c +++ b/src/wrapped/wrappedglib2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedgmodule2.c b/src/wrapped/wrappedgmodule2.c index 85e669a62..9157544a2 100644 --- a/src/wrapped/wrappedgmodule2.c +++ b/src/wrapped/wrappedgmodule2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgmp.c b/src/wrapped/wrappedgmp.c index aada01df3..add288b54 100644 --- a/src/wrapped/wrappedgmp.c +++ b/src/wrapped/wrappedgmp.c @@ -3,7 +3,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgnutls.c b/src/wrapped/wrappedgnutls.c index 0fdbbf9b8..2dd72b680 100644 --- a/src/wrapped/wrappedgnutls.c +++ b/src/wrapped/wrappedgnutls.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgobject2.c b/src/wrapped/wrappedgobject2.c index 4dfc63602..304b26530 100644 --- a/src/wrapped/wrappedgobject2.c +++ b/src/wrapped/wrappedgobject2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedgomp.c b/src/wrapped/wrappedgomp.c index 88f3bc599..69eedeb17 100644 --- a/src/wrapped/wrappedgomp.c +++ b/src/wrapped/wrappedgomp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgssapi.c b/src/wrapped/wrappedgssapi.c index ca9046439..940dc4f91 100644 --- a/src/wrapped/wrappedgssapi.c +++ b/src/wrapped/wrappedgssapi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgssapikrb5.c b/src/wrapped/wrappedgssapikrb5.c index aaba3dcaa..ef806b2a8 100644 --- a/src/wrapped/wrappedgssapikrb5.c +++ b/src/wrapped/wrappedgssapikrb5.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstallocators.c b/src/wrapped/wrappedgstallocators.c index 59e706508..839a1ebc5 100644 --- a/src/wrapped/wrappedgstallocators.c +++ b/src/wrapped/wrappedgstallocators.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstapp.c b/src/wrapped/wrappedgstapp.c index 0647da993..a478c47d5 100644 --- a/src/wrapped/wrappedgstapp.c +++ b/src/wrapped/wrappedgstapp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstaudio.c b/src/wrapped/wrappedgstaudio.c index 6bdecec1d..6e172ed1b 100644 --- a/src/wrapped/wrappedgstaudio.c +++ b/src/wrapped/wrappedgstaudio.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstbase.c b/src/wrapped/wrappedgstbase.c index 6da33294e..c5e53fd45 100644 --- a/src/wrapped/wrappedgstbase.c +++ b/src/wrapped/wrappedgstbase.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstcheck.c b/src/wrapped/wrappedgstcheck.c index 7a799eac2..51a27f11a 100644 --- a/src/wrapped/wrappedgstcheck.c +++ b/src/wrapped/wrappedgstcheck.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstcontroller.c b/src/wrapped/wrappedgstcontroller.c index 16893c730..9e4d26df4 100644 --- a/src/wrapped/wrappedgstcontroller.c +++ b/src/wrapped/wrappedgstcontroller.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstfft.c b/src/wrapped/wrappedgstfft.c index 7d95f0500..e7f808c04 100644 --- a/src/wrapped/wrappedgstfft.c +++ b/src/wrapped/wrappedgstfft.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstgl.c b/src/wrapped/wrappedgstgl.c index c3b9155f1..1455b09b2 100644 --- a/src/wrapped/wrappedgstgl.c +++ b/src/wrapped/wrappedgstgl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedgstnet.c b/src/wrapped/wrappedgstnet.c index c6b7fafa6..a23f0549a 100644 --- a/src/wrapped/wrappedgstnet.c +++ b/src/wrapped/wrappedgstnet.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstpbutils.c b/src/wrapped/wrappedgstpbutils.c index 4287ed972..2732fecd4 100644 --- a/src/wrapped/wrappedgstpbutils.c +++ b/src/wrapped/wrappedgstpbutils.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstreamer.c b/src/wrapped/wrappedgstreamer.c index a1b60778c..06adf2ee1 100644 --- a/src/wrapped/wrappedgstreamer.c +++ b/src/wrapped/wrappedgstreamer.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedgstriff.c b/src/wrapped/wrappedgstriff.c index baf46f071..e07bd29fc 100644 --- a/src/wrapped/wrappedgstriff.c +++ b/src/wrapped/wrappedgstriff.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstrtp.c b/src/wrapped/wrappedgstrtp.c index 0a6b4d69c..b8678dcde 100644 --- a/src/wrapped/wrappedgstrtp.c +++ b/src/wrapped/wrappedgstrtp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstrtsp.c b/src/wrapped/wrappedgstrtsp.c index a6b14a9fd..569cc2f57 100644 --- a/src/wrapped/wrappedgstrtsp.c +++ b/src/wrapped/wrappedgstrtsp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstsdp.c b/src/wrapped/wrappedgstsdp.c index 67f647411..dd2d55eac 100644 --- a/src/wrapped/wrappedgstsdp.c +++ b/src/wrapped/wrappedgstsdp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgsttag.c b/src/wrapped/wrappedgsttag.c index 5436ccb43..e7b9f63d1 100644 --- a/src/wrapped/wrappedgsttag.c +++ b/src/wrapped/wrappedgsttag.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgstvideo.c b/src/wrapped/wrappedgstvideo.c index 444a60c6a..d857f8ee7 100644 --- a/src/wrapped/wrappedgstvideo.c +++ b/src/wrapped/wrappedgstvideo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgthread2.c b/src/wrapped/wrappedgthread2.c index b0d455142..e4bd71385 100644 --- a/src/wrapped/wrappedgthread2.c +++ b/src/wrapped/wrappedgthread2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedgtk3.c b/src/wrapped/wrappedgtk3.c index 17d5a2a6b..3cd6ab335 100644 --- a/src/wrapped/wrappedgtk3.c +++ b/src/wrapped/wrappedgtk3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedgtkx112.c b/src/wrapped/wrappedgtkx112.c index d5efa8962..4c761de3c 100644 --- a/src/wrapped/wrappedgtkx112.c +++ b/src/wrapped/wrappedgtkx112.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedharfbuzzsubset.c b/src/wrapped/wrappedharfbuzzsubset.c index 4d03ba7b2..42bba0889 100644 --- a/src/wrapped/wrappedharfbuzzsubset.c +++ b/src/wrapped/wrappedharfbuzzsubset.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappediconv.c b/src/wrapped/wrappediconv.c index 685ade1aa..bb7e694c5 100644 --- a/src/wrapped/wrappediconv.c +++ b/src/wrapped/wrappediconv.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n64.c b/src/wrapped/wrappedicui18n64.c index 10c207124..451d45ec6 100644 --- a/src/wrapped/wrappedicui18n64.c +++ b/src/wrapped/wrappedicui18n64.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n66.c b/src/wrapped/wrappedicui18n66.c index 4f75d5337..94ebbe4b2 100644 --- a/src/wrapped/wrappedicui18n66.c +++ b/src/wrapped/wrappedicui18n66.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n67.c b/src/wrapped/wrappedicui18n67.c index 36decb15e..53fd0ea4a 100644 --- a/src/wrapped/wrappedicui18n67.c +++ b/src/wrapped/wrappedicui18n67.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n68.c b/src/wrapped/wrappedicui18n68.c index 9b9c909e4..1d953ca3c 100644 --- a/src/wrapped/wrappedicui18n68.c +++ b/src/wrapped/wrappedicui18n68.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n72.c b/src/wrapped/wrappedicui18n72.c index 450262dd2..b6d34e7a3 100644 --- a/src/wrapped/wrappedicui18n72.c +++ b/src/wrapped/wrappedicui18n72.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n73.c b/src/wrapped/wrappedicui18n73.c index 0054f66da..3af8d15a3 100644 --- a/src/wrapped/wrappedicui18n73.c +++ b/src/wrapped/wrappedicui18n73.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n74.c b/src/wrapped/wrappedicui18n74.c index 978411b9f..f36e2989d 100644 --- a/src/wrapped/wrappedicui18n74.c +++ b/src/wrapped/wrappedicui18n74.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n75.c b/src/wrapped/wrappedicui18n75.c index 51b388dfb..2854bc2e0 100644 --- a/src/wrapped/wrappedicui18n75.c +++ b/src/wrapped/wrappedicui18n75.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicui18n76.c b/src/wrapped/wrappedicui18n76.c index 647ab4902..a26673ac2 100644 --- a/src/wrapped/wrappedicui18n76.c +++ b/src/wrapped/wrappedicui18n76.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc64.c b/src/wrapped/wrappedicuuc64.c index af4dbdd0c..c5cff9fdd 100644 --- a/src/wrapped/wrappedicuuc64.c +++ b/src/wrapped/wrappedicuuc64.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc66.c b/src/wrapped/wrappedicuuc66.c index 368e1eb90..154e5fb4b 100644 --- a/src/wrapped/wrappedicuuc66.c +++ b/src/wrapped/wrappedicuuc66.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc67.c b/src/wrapped/wrappedicuuc67.c index ba6c70357..e3130edef 100644 --- a/src/wrapped/wrappedicuuc67.c +++ b/src/wrapped/wrappedicuuc67.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc68.c b/src/wrapped/wrappedicuuc68.c index 7ad658313..13a120f99 100644 --- a/src/wrapped/wrappedicuuc68.c +++ b/src/wrapped/wrappedicuuc68.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc72.c b/src/wrapped/wrappedicuuc72.c index 2147909f6..9a71af36d 100644 --- a/src/wrapped/wrappedicuuc72.c +++ b/src/wrapped/wrappedicuuc72.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc73.c b/src/wrapped/wrappedicuuc73.c index 5eda8a97c..92e6698c7 100644 --- a/src/wrapped/wrappedicuuc73.c +++ b/src/wrapped/wrappedicuuc73.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc74.c b/src/wrapped/wrappedicuuc74.c index d76a48c50..92dc67e7d 100644 --- a/src/wrapped/wrappedicuuc74.c +++ b/src/wrapped/wrappedicuuc74.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc75.c b/src/wrapped/wrappedicuuc75.c index 484dc50d4..e0984b73c 100644 --- a/src/wrapped/wrappedicuuc75.c +++ b/src/wrapped/wrappedicuuc75.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedicuuc76.c b/src/wrapped/wrappedicuuc76.c index 3a2d4d721..38f5891b1 100644 --- a/src/wrapped/wrappedicuuc76.c +++ b/src/wrapped/wrappedicuuc76.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedidn2.c b/src/wrapped/wrappedidn2.c index af6e9fade..adef4e98d 100644 --- a/src/wrapped/wrappedidn2.c +++ b/src/wrapped/wrappedidn2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedkrb5.c b/src/wrapped/wrappedkrb5.c index efd2651e3..7419131f0 100644 --- a/src/wrapped/wrappedkrb5.c +++ b/src/wrapped/wrappedkrb5.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlber.c b/src/wrapped/wrappedlber.c index 5f76acb0c..041e3cdcc 100644 --- a/src/wrapped/wrappedlber.c +++ b/src/wrapped/wrappedlber.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlcms2.c b/src/wrapped/wrappedlcms2.c index c95fc9969..5986d3913 100644 --- a/src/wrapped/wrappedlcms2.c +++ b/src/wrapped/wrappedlcms2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedldapr.c b/src/wrapped/wrappedldapr.c index b51afe860..0a37685e9 100644 --- a/src/wrapped/wrappedldapr.c +++ b/src/wrapped/wrappedldapr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedldlinux.c b/src/wrapped/wrappedldlinux.c index d84d3228e..9b6584ec5 100644 --- a/src/wrapped/wrappedldlinux.c +++ b/src/wrapped/wrappedldlinux.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibasound.c b/src/wrapped/wrappedlibasound.c index f4663de51..33ea2d072 100644 --- a/src/wrapped/wrappedlibasound.c +++ b/src/wrapped/wrappedlibasound.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedlibavcodec58.c b/src/wrapped/wrappedlibavcodec58.c index a805f0709..e7a50e04c 100644 --- a/src/wrapped/wrappedlibavcodec58.c +++ b/src/wrapped/wrappedlibavcodec58.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibavformat58.c b/src/wrapped/wrappedlibavformat58.c index 6197466f9..8472477a5 100644 --- a/src/wrapped/wrappedlibavformat58.c +++ b/src/wrapped/wrappedlibavformat58.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibavutil56.c b/src/wrapped/wrappedlibavutil56.c index 0a70b375a..7eb5e4601 100644 --- a/src/wrapped/wrappedlibavutil56.c +++ b/src/wrapped/wrappedlibavutil56.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #define __STDC_WANT_LIB_EXT2__ 1 // for vasprintf diff --git a/src/wrapped/wrappedlibblas.c b/src/wrapped/wrappedlibblas.c index 32a559fea..5b0b8ec69 100644 --- a/src/wrapped/wrappedlibblas.c +++ b/src/wrapped/wrappedlibblas.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibbsd.c b/src/wrapped/wrappedlibbsd.c index 3c1e9de83..5c1c7edcf 100644 --- a/src/wrapped/wrappedlibbsd.c +++ b/src/wrapped/wrappedlibbsd.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 10c0f34d4..e59bf76f4 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -1,7 +1,4 @@ // SPDX-License-Identifier: MIT -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 -#define _GNU_SOURCE /* See feature_test_macros(7) */ #if !defined(TERMUX) && !defined(ANDROID) # if defined(__has_include) # if __has_include() @@ -67,6 +64,7 @@ extern const char *const sys_siglist[] __asm__("__sys_siglist"); #include #include #include +#include #undef LOG_INFO #undef LOG_DEBUG @@ -444,7 +442,7 @@ static void* findcompare_dirFct(void* fct) // filter64 #define GO(A) \ static uintptr_t my_filter64_fct_##A = 0; \ -static int my_filter64_##A(const struct dirent64* a) \ +static int my_filter64_##A(const struct dirent* a) \ { \ return (int)RunFunctionFmt(my_filter64_fct_##A, "p", a); \ } @@ -467,7 +465,7 @@ static void* findfilter64Fct(void* fct) // compare64 #define GO(A) \ static uintptr_t my_compare64_fct_##A = 0; \ -static int my_compare64_##A(const struct dirent64* a, const struct dirent64* b) \ +static int my_compare64_##A(const struct dirent* a, const struct dirent* b) \ { \ return (int)RunFunctionFmt(my_compare64_fct_##A, "pp", a, b); \ } @@ -1705,8 +1703,8 @@ EXPORT void my__ITM_deregisterTMCloneTable(x64emu_t* emu, void* p) { (void)emu; EXPORT int my___fxstat(x64emu_t *emu, int vers, int fd, void* buf) { (void)emu; (void)vers; - struct stat64 st; - int r = fstat64(fd, buf?&st:buf); + struct stat st; + int r = fstat(fd, buf?&st:buf); if(buf && !r) UnalignStat64(&st, buf); return r; @@ -1747,8 +1745,8 @@ EXPORT int my___xmknodat(x64emu_t* emu, int v, int dirfd, char* path, uint32_t m EXPORT int my___xstat(x64emu_t* emu, int v, void* path, void* buf) { (void)emu; (void)v; - struct stat64 st; - int r = stat64((const char*)path, buf?&st:buf); + struct stat st; + int r = stat((const char*)path, buf?&st:buf); if(buf && !r) UnalignStat64(&st, buf); return r; @@ -1758,8 +1756,8 @@ EXPORT int my___xstat64(x64emu_t* emu, int v, void* path, void* buf) __attribute EXPORT int my___lxstat(x64emu_t* emu, int v, void* name, void* buf) { (void)emu; (void)v; - struct stat64 st; - int r = lstat64((const char*)name, buf?&st:buf); + struct stat st; + int r = lstat((const char*)name, buf?&st:buf); if(buf && !r) UnalignStat64(&st, buf); return r; @@ -1769,8 +1767,8 @@ EXPORT int my___lxstat64(x64emu_t* emu, int v, void* name, void* buf) __attribut EXPORT int my___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, int flags) { (void)emu; (void)v; - struct stat64 st; - int r = fstatat64(d, path, &st, flags); + struct stat st; + int r = fstatat(d, path, &st, flags); if(!r) UnalignStat64(&st, buf); return r; @@ -1823,7 +1821,7 @@ EXPORT int my_fstatat64(x64emu_t *emu, int fd, const char* path, void* buf, int EXPORT int my__IO_file_stat(x64emu_t* emu, void* f, void* buf) { - struct stat64 st; + struct stat st; int r = my->_IO_file_stat(f, &st); UnalignStat64(&st, buf); return r; @@ -1832,16 +1830,16 @@ EXPORT int my__IO_file_stat(x64emu_t* emu, void* f, void* buf) #if 0 EXPORT int my_fstatfs64(int fd, void* buf) { - struct statfs64 st; - int r = fstatfs64(fd, &st); + struct statfs st; + int r = fstatfs(fd, &st); UnalignStatFS64(&st, buf); return r; } EXPORT int my_statfs64(const char* path, void* buf) { - struct statfs64 st; - int r = statfs64(path, &st); + struct statfs st; + int r = statfs(path, &st); UnalignStatFS64(&st, buf); return r; } @@ -2032,7 +2030,7 @@ EXPORT void* my_readdir(x64emu_t* emu, void* dirp) { if (BOX64ENV(fix_64bit_inodes)) { - struct dirent64 *dp64 = readdir64((DIR *)dirp); + struct dirent *dp64 = readdir((DIR *)dirp); if (!dp64) return NULL; uint32_t ino32 = dp64->d_ino ^ (dp64->d_ino >> 32); int32_t off32 = dp64->d_off; @@ -2057,7 +2055,7 @@ EXPORT void* my_readdir(x64emu_t* emu, void* dirp) EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** result) { - struct dirent64 d64, *dp64; + struct dirent d64, *dp64; if (BOX64ENV(fix_64bit_inodes) && (sizeof(d64.d_name) > 1)) { static iFppp_t f = NULL; @@ -2068,7 +2066,7 @@ EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** resul *result = NULL; return 0; } - f = (iFppp_t)dlsym(lib->w.lib, "readdir64_r"); + f = (iFppp_t)dlsym(lib->w.lib, "readdir_r"); } int r = f(dirp, &d64, &dp64); @@ -2079,7 +2077,7 @@ EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** resul } struct i386_dirent *dp32 = (struct i386_dirent *)entry; - int namelen = dp64->d_reclen - offsetof(struct dirent64, d_name); + int namelen = dp64->d_reclen - offsetof(struct dirent, d_name); if (namelen > sizeof(dp32->d_name)) { *result = NULL; @@ -2163,6 +2161,17 @@ static long isProcMem(const char* path) } #define MAX_PATH_LENGTH 4096 +static int isPathPageReadable(uintptr_t page) +{ +#ifdef __NR_process_vm_readv + char c; + struct iovec local = { &c, 1 }; + struct iovec remote = { (void*)page, 1 }; + return syscall(__NR_process_vm_readv, getpid(), &local, 1, &remote, 1, 0) == 1; +#else + return 0; +#endif +} static int isPathValid(const char* path) { if(!path) @@ -2173,7 +2182,7 @@ static int isPathValid(const char* path) uintptr_t page = ALIGN_DOWN(p + i); if(page != cache_page) { cache_page = page; - if(!(getProtection_fast(cache_page) & PROT_READ)) + if(!(getProtection_fast(cache_page) & PROT_READ) && !isPathPageReadable(cache_page)) return 0; } if(!path[i]) @@ -2387,16 +2396,11 @@ enum { static int32_t open_func_fallback(char *pathname, int32_t flags, uint32_t open_mode, char *fopen_mode, int type, FILE **file) { - if (type == FOPEN64_TYPE) { - *file = fopen64(pathname, fopen_mode); - return 0; - } else if (type == FOPEN_TYPE) { + if (type == FOPEN_TYPE || type == FOPEN64_TYPE) { *file = fopen(pathname, fopen_mode); return 0; - } else if (type == OPEN_TYPE) { + } else if (type == OPEN_TYPE || type == OPEN64_TYPE) { return open(pathname, flags, open_mode); - } else if (type == OPEN64_TYPE) { - return open64(pathname, flags, open_mode); } return -1; } @@ -2654,7 +2658,7 @@ EXPORT int32_t my_epoll_pwait2(x64emu_t* emu, int epfd, void* events, int maxeve EXPORT int32_t my_glob64(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) { (void)emu; - return glob64(pat, flags, findgloberrFct(errfnc), pglob); + return glob(pat, flags, findgloberrFct(errfnc), pglob); } EXPORT int32_t my_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) __attribute__((alias("my_glob64"))); #endif @@ -2662,7 +2666,7 @@ EXPORT int32_t my_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, vo EXPORT int my_scandir64(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp) { (void)emu; - return scandir64(dir, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); + return scandir(dir, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); } EXPORT int my_scandir(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp) __attribute__((alias("my_scandir64"))); @@ -2675,20 +2679,20 @@ EXPORT int my_scandirat(x64emu_t *emu, int dirfd, void* dirp, void* namelist, vo EXPORT int my_scandirat64(x64emu_t *emu, int dirfd, void* dirp, void* namelist, void* sel, void* comp) { (void)emu; - return scandirat64(dirfd, dirp, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); + return scandirat(dirfd, dirp, namelist, findfilter64Fct(sel), findcompare64Fct(comp)); } EXPORT int my_ftw64(x64emu_t* emu, void* filename, void* func, int descriptors) { (void)emu; - return ftw64(filename, findftw64Fct(func), descriptors); + return ftw(filename, findftw64Fct(func), descriptors); } EXPORT int my_ftw(x64emu_t* emu, void* filename, void* func, int descriptors) __attribute__((alias("my_ftw64"))); EXPORT int32_t my_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) { (void)emu; - return nftw64(pathname, findnftw64Fct(B), nopenfd, flags); + return nftw(pathname, findnftw64Fct(B), nopenfd, flags); } EXPORT int my_nftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) __attribute__((alias("my_nftw64"))); @@ -4262,7 +4266,7 @@ static ssize_t my_cookie_write(void *p, const char *buf, size_t size) my_cookie_t* cookie = (my_cookie_t*)p; return (ssize_t)RunFunctionFmt(cookie->w, "ppL", cookie->cookie, buf, size) ; } -static int my_cookie_seek(void *p, off64_t *offset, int whence) +static int my_cookie_seek(void *p, off_t *offset, int whence) { my_cookie_t* cookie = (my_cookie_t*)p; return RunFunctionFmt(cookie->s, "ppi", cookie->cookie, offset, whence) ; @@ -4382,10 +4386,10 @@ EXPORT int my_getrlimit(x64emu_t* emu, uint32_t resource, struct rlimit* rlim) return my___getrlimit(emu, resource, rlim); } -EXPORT int my_getrlimit64(x64emu_t* emu, uint32_t resource, struct rlimit64* rlim) +EXPORT int my_getrlimit64(x64emu_t* emu, uint32_t resource, struct rlimit* rlim) { (void)emu; - return check_getrlimit_buffer(rlim, sizeof(*rlim)) ? getrlimit64(resource, rlim) : -1; + return check_getrlimit_buffer(rlim, sizeof(*rlim)) ? getrlimit(resource, rlim) : -1; } EXPORT int my_setrlimit(x64emu_t* emu, int ressource, const struct rlimit *rlim) diff --git a/src/wrapped/wrappedlibcmusl.c b/src/wrapped/wrappedlibcmusl.c index e66471df0..603beb4b3 100644 --- a/src/wrapped/wrappedlibcmusl.c +++ b/src/wrapped/wrappedlibcmusl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibcrypt.c b/src/wrapped/wrappedlibcrypt.c index f033d705b..cf75b4da3 100644 --- a/src/wrapped/wrappedlibcrypt.c +++ b/src/wrapped/wrappedlibcrypt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibcups.c b/src/wrapped/wrappedlibcups.c index ecd745377..33ae36a10 100644 --- a/src/wrapped/wrappedlibcups.c +++ b/src/wrapped/wrappedlibcups.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibcupsimage.c b/src/wrapped/wrappedlibcupsimage.c index aee69284a..2aa4f44b5 100644 --- a/src/wrapped/wrappedlibcupsimage.c +++ b/src/wrapped/wrappedlibcupsimage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index 0d69d80ff..38cfc2b58 100644 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibdrm.c b/src/wrapped/wrappedlibdrm.c index 47a6f59c2..a7cc51041 100644 --- a/src/wrapped/wrappedlibdrm.c +++ b/src/wrapped/wrappedlibdrm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibdrmamdgpu.c b/src/wrapped/wrappedlibdrmamdgpu.c index 08778ec36..d8aa6b626 100644 --- a/src/wrapped/wrappedlibdrmamdgpu.c +++ b/src/wrapped/wrappedlibdrmamdgpu.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibegl.c b/src/wrapped/wrappedlibegl.c index 23e16305a..f0177990f 100644 --- a/src/wrapped/wrappedlibegl.c +++ b/src/wrapped/wrappedlibegl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibform.c b/src/wrapped/wrappedlibform.c index e435049c1..d995e4b97 100644 --- a/src/wrapped/wrappedlibform.c +++ b/src/wrapped/wrappedlibform.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibformw.c b/src/wrapped/wrappedlibformw.c index 0a8b178d3..9a51cb742 100644 --- a/src/wrapped/wrappedlibformw.c +++ b/src/wrapped/wrappedlibformw.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibformw6.c b/src/wrapped/wrappedlibformw6.c index dbe66b9fd..7a39583a8 100644 --- a/src/wrapped/wrappedlibformw6.c +++ b/src/wrapped/wrappedlibformw6.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibfuse.c b/src/wrapped/wrappedlibfuse.c index f062a5f4c..f03eeda10 100644 --- a/src/wrapped/wrappedlibfuse.c +++ b/src/wrapped/wrappedlibfuse.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedlibgl.c b/src/wrapped/wrappedlibgl.c index f813ef2c9..7969aeba4 100644 --- a/src/wrapped/wrappedlibgl.c +++ b/src/wrapped/wrappedlibgl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibglu.c b/src/wrapped/wrappedlibglu.c index 0bc1f48f4..46d513465 100644 --- a/src/wrapped/wrappedlibglu.c +++ b/src/wrapped/wrappedlibglu.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibglx.c b/src/wrapped/wrappedlibglx.c index 1d78a166c..102119103 100644 --- a/src/wrapped/wrappedlibglx.c +++ b/src/wrapped/wrappedlibglx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibglxnvidia.c b/src/wrapped/wrappedlibglxnvidia.c index b61e57942..b007693df 100644 --- a/src/wrapped/wrappedlibglxnvidia.c +++ b/src/wrapped/wrappedlibglxnvidia.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibgpgme.c b/src/wrapped/wrappedlibgpgme.c index a3bfe92b7..f5df43cfe 100644 --- a/src/wrapped/wrappedlibgpgme.c +++ b/src/wrapped/wrappedlibgpgme.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibharfbuzz.c b/src/wrapped/wrappedlibharfbuzz.c index 07d10cede..6b5f9411f 100644 --- a/src/wrapped/wrappedlibharfbuzz.c +++ b/src/wrapped/wrappedlibharfbuzz.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" #include "wrapper.h" diff --git a/src/wrapped/wrappedlibhogweed6.c b/src/wrapped/wrappedlibhogweed6.c index 6041a06b9..3e5f759ae 100644 --- a/src/wrapped/wrappedlibhogweed6.c +++ b/src/wrapped/wrappedlibhogweed6.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibibus.c b/src/wrapped/wrappedlibibus.c index 2b1e638ef..63cfbfa98 100644 --- a/src/wrapped/wrappedlibibus.c +++ b/src/wrapped/wrappedlibibus.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibice.c b/src/wrapped/wrappedlibice.c index c09c6184f..a4f4094f7 100644 --- a/src/wrapped/wrappedlibice.c +++ b/src/wrapped/wrappedlibice.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedliblapack.c b/src/wrapped/wrappedliblapack.c index 9354fa15f..ed3383a92 100644 --- a/src/wrapped/wrappedliblapack.c +++ b/src/wrapped/wrappedliblapack.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibm.c b/src/wrapped/wrappedlibm.c index af20b872a..e35569a70 100644 --- a/src/wrapped/wrappedlibm.c +++ b/src/wrapped/wrappedlibm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibmvec.c b/src/wrapped/wrappedlibmvec.c index 6a7cbaf93..39534c089 100644 --- a/src/wrapped/wrappedlibmvec.c +++ b/src/wrapped/wrappedlibmvec.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibncurses.c b/src/wrapped/wrappedlibncurses.c index 93fd9a41c..a0ca7522f 100644 --- a/src/wrapped/wrappedlibncurses.c +++ b/src/wrapped/wrappedlibncurses.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibncurses6.c b/src/wrapped/wrappedlibncurses6.c index b9e5dcac0..9e77ba5c6 100644 --- a/src/wrapped/wrappedlibncurses6.c +++ b/src/wrapped/wrappedlibncurses6.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibncursesw.c b/src/wrapped/wrappedlibncursesw.c index c7d9dba46..23e7ec53d 100644 --- a/src/wrapped/wrappedlibncursesw.c +++ b/src/wrapped/wrappedlibncursesw.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibncursesw6.c b/src/wrapped/wrappedlibncursesw6.c index efc9319e3..a306e7190 100644 --- a/src/wrapped/wrappedlibncursesw6.c +++ b/src/wrapped/wrappedlibncursesw6.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibnettle8.c b/src/wrapped/wrappedlibnettle8.c index 11bb66ebb..925fefaa6 100644 --- a/src/wrapped/wrappedlibnettle8.c +++ b/src/wrapped/wrappedlibnettle8.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibnuma.c b/src/wrapped/wrappedlibnuma.c index 2921e3fce..53933dd2a 100644 --- a/src/wrapped/wrappedlibnuma.c +++ b/src/wrapped/wrappedlibnuma.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibogg.c b/src/wrapped/wrappedlibogg.c index 42281b64f..3a69d1e16 100644 --- a/src/wrapped/wrappedlibogg.c +++ b/src/wrapped/wrappedlibogg.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibomp.c b/src/wrapped/wrappedlibomp.c index 75bb90f8e..e4dc3e0e2 100644 --- a/src/wrapped/wrappedlibomp.c +++ b/src/wrapped/wrappedlibomp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibopus.c b/src/wrapped/wrappedlibopus.c index 956c36066..1a9cdd3e5 100644 --- a/src/wrapped/wrappedlibopus.c +++ b/src/wrapped/wrappedlibopus.c @@ -3,7 +3,6 @@ #include #include #include -#define _GNU_SOURCE #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpanel.c b/src/wrapped/wrappedlibpanel.c index 3f7cd2b98..ae3e38f3f 100644 --- a/src/wrapped/wrappedlibpanel.c +++ b/src/wrapped/wrappedlibpanel.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibpci.c b/src/wrapped/wrappedlibpci.c index 24753ed72..8f5a671b4 100644 --- a/src/wrapped/wrappedlibpci.c +++ b/src/wrapped/wrappedlibpci.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpcre.c b/src/wrapped/wrappedlibpcre.c index 248a7a85d..143a67460 100644 --- a/src/wrapped/wrappedlibpcre.c +++ b/src/wrapped/wrappedlibpcre.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpcre216.c b/src/wrapped/wrappedlibpcre216.c index 8e538f926..ea499bffc 100644 --- a/src/wrapped/wrappedlibpcre216.c +++ b/src/wrapped/wrappedlibpcre216.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibpthread.c b/src/wrapped/wrappedlibpthread.c index 91330f299..be0761272 100644 --- a/src/wrapped/wrappedlibpthread.c +++ b/src/wrapped/wrappedlibpthread.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT #define __USE_UNIX98 -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibresolv.c b/src/wrapped/wrappedlibresolv.c index 12dfe7bdf..e99c02b01 100644 --- a/src/wrapped/wrappedlibresolv.c +++ b/src/wrapped/wrappedlibresolv.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibrt.c b/src/wrapped/wrappedlibrt.c index 46e4c03c3..f1c2239ad 100644 --- a/src/wrapped/wrappedlibrt.c +++ b/src/wrapped/wrappedlibrt.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedlibsm.c b/src/wrapped/wrappedlibsm.c index 7f34ec59d..d89968f53 100644 --- a/src/wrapped/wrappedlibsm.c +++ b/src/wrapped/wrappedlibsm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibsndfile.c b/src/wrapped/wrappedlibsndfile.c index ce5346d6a..cb45a8efc 100644 --- a/src/wrapped/wrappedlibsndfile.c +++ b/src/wrapped/wrappedlibsndfile.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibsqlite3.c b/src/wrapped/wrappedlibsqlite3.c index 192e0ac15..fe709166b 100644 --- a/src/wrapped/wrappedlibsqlite3.c +++ b/src/wrapped/wrappedlibsqlite3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibssh2.c b/src/wrapped/wrappedlibssh2.c index 6d552271c..a4d8edd80 100644 --- a/src/wrapped/wrappedlibssh2.c +++ b/src/wrapped/wrappedlibssh2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibssl.c b/src/wrapped/wrappedlibssl.c index 4fb8f5df6..7e7747440 100644 --- a/src/wrapped/wrappedlibssl.c +++ b/src/wrapped/wrappedlibssl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibssl3.c b/src/wrapped/wrappedlibssl3.c index 1f9369517..f9417531e 100644 --- a/src/wrapped/wrappedlibssl3.c +++ b/src/wrapped/wrappedlibssl3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibtasn1.c b/src/wrapped/wrappedlibtasn1.c index 429146806..0dd1d2648 100644 --- a/src/wrapped/wrappedlibtasn1.c +++ b/src/wrapped/wrappedlibtasn1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibtiff5.c b/src/wrapped/wrappedlibtiff5.c index 2b661a7e4..6c72de86b 100644 --- a/src/wrapped/wrappedlibtiff5.c +++ b/src/wrapped/wrappedlibtiff5.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibtinfo.c b/src/wrapped/wrappedlibtinfo.c index f0485f3b0..129368542 100644 --- a/src/wrapped/wrappedlibtinfo.c +++ b/src/wrapped/wrappedlibtinfo.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibtinfo6.c b/src/wrapped/wrappedlibtinfo6.c index af63d9520..e2f9ed400 100644 --- a/src/wrapped/wrappedlibtinfo6.c +++ b/src/wrapped/wrappedlibtinfo6.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibunistring2.c b/src/wrapped/wrappedlibunistring2.c index 53d4988a1..8bdbb6690 100644 --- a/src/wrapped/wrappedlibunistring2.c +++ b/src/wrapped/wrappedlibunistring2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibusb1.c b/src/wrapped/wrappedlibusb1.c index cf23b6f78..5b2bf3c69 100644 --- a/src/wrapped/wrappedlibusb1.c +++ b/src/wrapped/wrappedlibusb1.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibuuid.c b/src/wrapped/wrappedlibuuid.c index 51690304d..0ab12666b 100644 --- a/src/wrapped/wrappedlibuuid.c +++ b/src/wrapped/wrappedlibuuid.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibva.c b/src/wrapped/wrappedlibva.c index a51bf6a0a..3d4349401 100644 --- a/src/wrapped/wrappedlibva.c +++ b/src/wrapped/wrappedlibva.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvadrm.c b/src/wrapped/wrappedlibvadrm.c index 9ff2dbfea..51ea4b1a3 100644 --- a/src/wrapped/wrappedlibvadrm.c +++ b/src/wrapped/wrappedlibvadrm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvawayland.c b/src/wrapped/wrappedlibvawayland.c index 0a940e919..454320b7a 100644 --- a/src/wrapped/wrappedlibvawayland.c +++ b/src/wrapped/wrappedlibvawayland.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvax11.c b/src/wrapped/wrappedlibvax11.c index 174b5e189..af0669fbe 100644 --- a/src/wrapped/wrappedlibvax11.c +++ b/src/wrapped/wrappedlibvax11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvdpau.c b/src/wrapped/wrappedlibvdpau.c index 358438ce9..52b3632f1 100644 --- a/src/wrapped/wrappedlibvdpau.c +++ b/src/wrapped/wrappedlibvdpau.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvorbis.c b/src/wrapped/wrappedlibvorbis.c index e9e896e30..478030d6a 100644 --- a/src/wrapped/wrappedlibvorbis.c +++ b/src/wrapped/wrappedlibvorbis.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibvpx.c b/src/wrapped/wrappedlibvpx.c index 1d10a6c6b..97f6bd3e7 100644 --- a/src/wrapped/wrappedlibvpx.c +++ b/src/wrapped/wrappedlibvpx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibx11.c b/src/wrapped/wrappedlibx11.c index e31c6c52e..40281ff85 100644 --- a/src/wrapped/wrappedlibx11.c +++ b/src/wrapped/wrappedlibx11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibx11xcb.c b/src/wrapped/wrappedlibx11xcb.c index 3fb4e54d3..075de6e1c 100644 --- a/src/wrapped/wrappedlibx11xcb.c +++ b/src/wrapped/wrappedlibx11xcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxau.c b/src/wrapped/wrappedlibxau.c index c1236771f..5803acccc 100644 --- a/src/wrapped/wrappedlibxau.c +++ b/src/wrapped/wrappedlibxau.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxaw.c b/src/wrapped/wrappedlibxaw.c index ae5e48257..c5c2d4db9 100644 --- a/src/wrapped/wrappedlibxaw.c +++ b/src/wrapped/wrappedlibxaw.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcb.c b/src/wrapped/wrappedlibxcb.c index 6ba006319..0241f0b36 100644 --- a/src/wrapped/wrappedlibxcb.c +++ b/src/wrapped/wrappedlibxcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbcursor.c b/src/wrapped/wrappedlibxcbcursor.c index 6c92e9c68..10fee4fad 100644 --- a/src/wrapped/wrappedlibxcbcursor.c +++ b/src/wrapped/wrappedlibxcbcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbdri2.c b/src/wrapped/wrappedlibxcbdri2.c index 59110263f..92f46d682 100644 --- a/src/wrapped/wrappedlibxcbdri2.c +++ b/src/wrapped/wrappedlibxcbdri2.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibxcbdri3.c b/src/wrapped/wrappedlibxcbdri3.c index 9969f507b..95d01d9a9 100644 --- a/src/wrapped/wrappedlibxcbdri3.c +++ b/src/wrapped/wrappedlibxcbdri3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlibxcbglx.c b/src/wrapped/wrappedlibxcbglx.c index 4737db47d..3dc021b34 100644 --- a/src/wrapped/wrappedlibxcbglx.c +++ b/src/wrapped/wrappedlibxcbglx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbicccm.c b/src/wrapped/wrappedlibxcbicccm.c index 89d90c56d..7b0f46ce7 100644 --- a/src/wrapped/wrappedlibxcbicccm.c +++ b/src/wrapped/wrappedlibxcbicccm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbimage.c b/src/wrapped/wrappedlibxcbimage.c index 602a91aa2..9c796eebd 100644 --- a/src/wrapped/wrappedlibxcbimage.c +++ b/src/wrapped/wrappedlibxcbimage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbkeysyms.c b/src/wrapped/wrappedlibxcbkeysyms.c index 21993bd93..6ee2db016 100644 --- a/src/wrapped/wrappedlibxcbkeysyms.c +++ b/src/wrapped/wrappedlibxcbkeysyms.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbpresent.c b/src/wrapped/wrappedlibxcbpresent.c index 516178c7c..c48331836 100644 --- a/src/wrapped/wrappedlibxcbpresent.c +++ b/src/wrapped/wrappedlibxcbpresent.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbrandr.c b/src/wrapped/wrappedlibxcbrandr.c index 4e8f8578e..b24afae30 100644 --- a/src/wrapped/wrappedlibxcbrandr.c +++ b/src/wrapped/wrappedlibxcbrandr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbrender.c b/src/wrapped/wrappedlibxcbrender.c index 3a867fbc4..0e7ff71b2 100644 --- a/src/wrapped/wrappedlibxcbrender.c +++ b/src/wrapped/wrappedlibxcbrender.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbrenderutil.c b/src/wrapped/wrappedlibxcbrenderutil.c index 27573195e..8af643215 100644 --- a/src/wrapped/wrappedlibxcbrenderutil.c +++ b/src/wrapped/wrappedlibxcbrenderutil.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbres.c b/src/wrapped/wrappedlibxcbres.c index 972a18578..547f86da8 100644 --- a/src/wrapped/wrappedlibxcbres.c +++ b/src/wrapped/wrappedlibxcbres.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbshape.c b/src/wrapped/wrappedlibxcbshape.c index 501da8a1b..e11ed2458 100644 --- a/src/wrapped/wrappedlibxcbshape.c +++ b/src/wrapped/wrappedlibxcbshape.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbshm.c b/src/wrapped/wrappedlibxcbshm.c index 1514236e7..1144356dc 100644 --- a/src/wrapped/wrappedlibxcbshm.c +++ b/src/wrapped/wrappedlibxcbshm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbsync.c b/src/wrapped/wrappedlibxcbsync.c index ec633c423..97e21e8bb 100644 --- a/src/wrapped/wrappedlibxcbsync.c +++ b/src/wrapped/wrappedlibxcbsync.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbutil.c b/src/wrapped/wrappedlibxcbutil.c index f453aac79..cdc5df9fb 100644 --- a/src/wrapped/wrappedlibxcbutil.c +++ b/src/wrapped/wrappedlibxcbutil.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxfixes.c b/src/wrapped/wrappedlibxcbxfixes.c index da2ace20d..bd67a0ae1 100644 --- a/src/wrapped/wrappedlibxcbxfixes.c +++ b/src/wrapped/wrappedlibxcbxfixes.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxinerama.c b/src/wrapped/wrappedlibxcbxinerama.c index 76835fdf2..f611973ea 100644 --- a/src/wrapped/wrappedlibxcbxinerama.c +++ b/src/wrapped/wrappedlibxcbxinerama.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxinput.c b/src/wrapped/wrappedlibxcbxinput.c index b5a339763..af80dadc3 100644 --- a/src/wrapped/wrappedlibxcbxinput.c +++ b/src/wrapped/wrappedlibxcbxinput.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxkb.c b/src/wrapped/wrappedlibxcbxkb.c index 3f0751c4f..ea656e90e 100644 --- a/src/wrapped/wrappedlibxcbxkb.c +++ b/src/wrapped/wrappedlibxcbxkb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcbxtest.c b/src/wrapped/wrappedlibxcbxtest.c index 23e6c39fe..372e38099 100644 --- a/src/wrapped/wrappedlibxcbxtest.c +++ b/src/wrapped/wrappedlibxcbxtest.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcomposite.c b/src/wrapped/wrappedlibxcomposite.c index ef25c209d..de5918bbb 100644 --- a/src/wrapped/wrappedlibxcomposite.c +++ b/src/wrapped/wrappedlibxcomposite.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxcursor.c b/src/wrapped/wrappedlibxcursor.c index fc5bdd564..009fa3842 100644 --- a/src/wrapped/wrappedlibxcursor.c +++ b/src/wrapped/wrappedlibxcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxdamage.c b/src/wrapped/wrappedlibxdamage.c index 3d7510e4b..438b43438 100644 --- a/src/wrapped/wrappedlibxdamage.c +++ b/src/wrapped/wrappedlibxdamage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxdmcp.c b/src/wrapped/wrappedlibxdmcp.c index 0a32487a0..e94cc36cc 100644 --- a/src/wrapped/wrappedlibxdmcp.c +++ b/src/wrapped/wrappedlibxdmcp.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxext.c b/src/wrapped/wrappedlibxext.c index 4f1d19d94..ef257f2e5 100644 --- a/src/wrapped/wrappedlibxext.c +++ b/src/wrapped/wrappedlibxext.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxfixes.c b/src/wrapped/wrappedlibxfixes.c index c981c2667..74cac9bbc 100644 --- a/src/wrapped/wrappedlibxfixes.c +++ b/src/wrapped/wrappedlibxfixes.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxft.c b/src/wrapped/wrappedlibxft.c index cd2590c1b..b27f746d1 100644 --- a/src/wrapped/wrappedlibxft.c +++ b/src/wrapped/wrappedlibxft.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxi.c b/src/wrapped/wrappedlibxi.c index 34105a733..cb2b2b5a3 100644 --- a/src/wrapped/wrappedlibxi.c +++ b/src/wrapped/wrappedlibxi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxmu.c b/src/wrapped/wrappedlibxmu.c index 56ec97a7f..d862846d5 100644 --- a/src/wrapped/wrappedlibxmu.c +++ b/src/wrapped/wrappedlibxmu.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxpm.c b/src/wrapped/wrappedlibxpm.c index f3fef5c4e..975359a50 100644 --- a/src/wrapped/wrappedlibxpm.c +++ b/src/wrapped/wrappedlibxpm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxpresent.c b/src/wrapped/wrappedlibxpresent.c index d73c668f0..7b56275cd 100644 --- a/src/wrapped/wrappedlibxpresent.c +++ b/src/wrapped/wrappedlibxpresent.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxrandr.c b/src/wrapped/wrappedlibxrandr.c index ddc40c2eb..cc00de4c7 100644 --- a/src/wrapped/wrappedlibxrandr.c +++ b/src/wrapped/wrappedlibxrandr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxrender.c b/src/wrapped/wrappedlibxrender.c index ba79706c0..6983b408a 100644 --- a/src/wrapped/wrappedlibxrender.c +++ b/src/wrapped/wrappedlibxrender.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxss.c b/src/wrapped/wrappedlibxss.c index 507216e16..06d4cd6e3 100644 --- a/src/wrapped/wrappedlibxss.c +++ b/src/wrapped/wrappedlibxss.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxt.c b/src/wrapped/wrappedlibxt.c index 4e305ee42..0bf3056fd 100644 --- a/src/wrapped/wrappedlibxt.c +++ b/src/wrapped/wrappedlibxt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxtst.c b/src/wrapped/wrappedlibxtst.c index e17621a33..c18842a07 100644 --- a/src/wrapped/wrappedlibxtst.c +++ b/src/wrapped/wrappedlibxtst.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibxxf86vm.c b/src/wrapped/wrappedlibxxf86vm.c index d5d04c332..104874386 100644 --- a/src/wrapped/wrappedlibxxf86vm.c +++ b/src/wrapped/wrappedlibxxf86vm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlibz.c b/src/wrapped/wrappedlibz.c index e57fb21c1..2daf998e1 100644 --- a/src/wrapped/wrappedlibz.c +++ b/src/wrapped/wrappedlibz.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedlz4.c b/src/wrapped/wrappedlz4.c index 1b789e75e..5e2867949 100644 --- a/src/wrapped/wrappedlz4.c +++ b/src/wrapped/wrappedlz4.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedlzma.c b/src/wrapped/wrappedlzma.c index 6ccce691c..0c19775ed 100644 --- a/src/wrapped/wrappedlzma.c +++ b/src/wrapped/wrappedlzma.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedmimalloc.c b/src/wrapped/wrappedmimalloc.c index 242fd29d7..ce9b4409f 100644 --- a/src/wrapped/wrappedmimalloc.c +++ b/src/wrapped/wrappedmimalloc.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedmpg123.c b/src/wrapped/wrappedmpg123.c index 1f5fb47ed..ea6f3d166 100644 --- a/src/wrapped/wrappedmpg123.c +++ b/src/wrapped/wrappedmpg123.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappednotify.c b/src/wrapped/wrappednotify.c index 0d9954e59..27a2ee79a 100644 --- a/src/wrapped/wrappednotify.c +++ b/src/wrapped/wrappednotify.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednsl.c b/src/wrapped/wrappednsl.c index fa47f9ec5..c410be90d 100644 --- a/src/wrapped/wrappednsl.c +++ b/src/wrapped/wrappednsl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednspr4.c b/src/wrapped/wrappednspr4.c index 689dde185..6023f54a4 100644 --- a/src/wrapped/wrappednspr4.c +++ b/src/wrapped/wrappednspr4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednss3.c b/src/wrapped/wrappednss3.c index 39425ff55..5d3fa4625 100644 --- a/src/wrapped/wrappednss3.c +++ b/src/wrapped/wrappednss3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednssutil3.c b/src/wrapped/wrappednssutil3.c index 045b0cb5a..dba8d0669 100644 --- a/src/wrapped/wrappednssutil3.c +++ b/src/wrapped/wrappednssutil3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappednvml.c b/src/wrapped/wrappednvml.c index 21acd75cc..9863535bc 100644 --- a/src/wrapped/wrappednvml.c +++ b/src/wrapped/wrappednvml.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedopenal.c b/src/wrapped/wrappedopenal.c index 76eb0f81c..3f56b888a 100644 --- a/src/wrapped/wrappedopenal.c +++ b/src/wrapped/wrappedopenal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedopencl.c b/src/wrapped/wrappedopencl.c index 881b640a5..806b31e1e 100644 --- a/src/wrapped/wrappedopencl.c +++ b/src/wrapped/wrappedopencl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedp11kit.c b/src/wrapped/wrappedp11kit.c index 490d96fdf..ef8b33505 100644 --- a/src/wrapped/wrappedp11kit.c +++ b/src/wrapped/wrappedp11kit.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpam.c b/src/wrapped/wrappedpam.c index 7b5f22a52..31a1c5f92 100644 --- a/src/wrapped/wrappedpam.c +++ b/src/wrapped/wrappedpam.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpango.c b/src/wrapped/wrappedpango.c index b5c4a5a5f..86de1792d 100644 --- a/src/wrapped/wrappedpango.c +++ b/src/wrapped/wrappedpango.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpangocairo.c b/src/wrapped/wrappedpangocairo.c index 89a60438f..eb6bfb808 100644 --- a/src/wrapped/wrappedpangocairo.c +++ b/src/wrapped/wrappedpangocairo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpangoft2.c b/src/wrapped/wrappedpangoft2.c index 7fb9d7077..182e8a1b9 100644 --- a/src/wrapped/wrappedpangoft2.c +++ b/src/wrapped/wrappedpangoft2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpcap.c b/src/wrapped/wrappedpcap.c index 188301b31..b0661f3a1 100644 --- a/src/wrapped/wrappedpcap.c +++ b/src/wrapped/wrappedpcap.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedpixman1.c b/src/wrapped/wrappedpixman1.c index 02b2c8a8d..77b029a0d 100644 --- a/src/wrapped/wrappedpixman1.c +++ b/src/wrapped/wrappedpixman1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedplc4.c b/src/wrapped/wrappedplc4.c index 0987cf42e..b4a083e9a 100644 --- a/src/wrapped/wrappedplc4.c +++ b/src/wrapped/wrappedplc4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedplds4.c b/src/wrapped/wrappedplds4.c index 4fbcd07e3..0b5c39830 100644 --- a/src/wrapped/wrappedplds4.c +++ b/src/wrapped/wrappedplds4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpng16.c b/src/wrapped/wrappedpng16.c index 98db87773..c08379457 100644 --- a/src/wrapped/wrappedpng16.c +++ b/src/wrapped/wrappedpng16.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedproxy.c b/src/wrapped/wrappedproxy.c index c423b81b7..97f4f745d 100644 --- a/src/wrapped/wrappedproxy.c +++ b/src/wrapped/wrappedproxy.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpsl5.c b/src/wrapped/wrappedpsl5.c index 9c196b281..7a548604e 100644 --- a/src/wrapped/wrappedpsl5.c +++ b/src/wrapped/wrappedpsl5.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpulse.c b/src/wrapped/wrappedpulse.c index af4dc3c72..d0a041876 100644 --- a/src/wrapped/wrappedpulse.c +++ b/src/wrapped/wrappedpulse.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedpulsemainloopglib.c b/src/wrapped/wrappedpulsemainloopglib.c index 3e03e05f5..72e5c9abd 100644 --- a/src/wrapped/wrappedpulsemainloopglib.c +++ b/src/wrapped/wrappedpulsemainloopglib.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedpulsesimple.c b/src/wrapped/wrappedpulsesimple.c index 26f6d9339..1f60dca50 100644 --- a/src/wrapped/wrappedpulsesimple.c +++ b/src/wrapped/wrappedpulsesimple.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1.c b/src/wrapped/wrappedsdl1.c index a257d4b02..a6c0acba9 100644 --- a/src/wrapped/wrappedsdl1.c +++ b/src/wrapped/wrappedsdl1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1image.c b/src/wrapped/wrappedsdl1image.c index 39522662a..bcbff5522 100644 --- a/src/wrapped/wrappedsdl1image.c +++ b/src/wrapped/wrappedsdl1image.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1mixer.c b/src/wrapped/wrappedsdl1mixer.c index 4ea78e97d..da53b37fe 100644 --- a/src/wrapped/wrappedsdl1mixer.c +++ b/src/wrapped/wrappedsdl1mixer.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1net.c b/src/wrapped/wrappedsdl1net.c index f29aeb536..244330d64 100644 --- a/src/wrapped/wrappedsdl1net.c +++ b/src/wrapped/wrappedsdl1net.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1sound.c b/src/wrapped/wrappedsdl1sound.c index 760a06a66..3538ecf45 100644 --- a/src/wrapped/wrappedsdl1sound.c +++ b/src/wrapped/wrappedsdl1sound.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl1ttf.c b/src/wrapped/wrappedsdl1ttf.c index 79c9d784d..051847e80 100644 --- a/src/wrapped/wrappedsdl1ttf.c +++ b/src/wrapped/wrappedsdl1ttf.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2.c b/src/wrapped/wrappedsdl2.c index 7f482e6da..bee79df9e 100644 --- a/src/wrapped/wrappedsdl2.c +++ b/src/wrapped/wrappedsdl2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedsdl2image.c b/src/wrapped/wrappedsdl2image.c index 2c15efdfe..8ebcc3aeb 100644 --- a/src/wrapped/wrappedsdl2image.c +++ b/src/wrapped/wrappedsdl2image.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2mixer.c b/src/wrapped/wrappedsdl2mixer.c index 6b35e24c1..2864dac29 100644 --- a/src/wrapped/wrappedsdl2mixer.c +++ b/src/wrapped/wrappedsdl2mixer.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2net.c b/src/wrapped/wrappedsdl2net.c index 05039c155..28ccf6ed3 100644 --- a/src/wrapped/wrappedsdl2net.c +++ b/src/wrapped/wrappedsdl2net.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl2ttf.c b/src/wrapped/wrappedsdl2ttf.c index 71951b566..55a4cb4b3 100644 --- a/src/wrapped/wrappedsdl2ttf.c +++ b/src/wrapped/wrappedsdl2ttf.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl3.c b/src/wrapped/wrappedsdl3.c index b71d4bde7..1bdd34a6f 100644 --- a/src/wrapped/wrappedsdl3.c +++ b/src/wrapped/wrappedsdl3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsdl3ttf.c b/src/wrapped/wrappedsdl3ttf.c index 7efcfd3bd..836d66acf 100644 --- a/src/wrapped/wrappedsdl3ttf.c +++ b/src/wrapped/wrappedsdl3ttf.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsecret1.c b/src/wrapped/wrappedsecret1.c index 058b91991..5cd189eed 100644 --- a/src/wrapped/wrappedsecret1.c +++ b/src/wrapped/wrappedsecret1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedselinux.c b/src/wrapped/wrappedselinux.c index 038b771c7..426607dcf 100644 --- a/src/wrapped/wrappedselinux.c +++ b/src/wrapped/wrappedselinux.c @@ -5,7 +5,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmbclient.c b/src/wrapped/wrappedsmbclient.c index 7d4bbae25..659c6f269 100644 --- a/src/wrapped/wrappedsmbclient.c +++ b/src/wrapped/wrappedsmbclient.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmime3.c b/src/wrapped/wrappedsmime3.c index 49a010332..d6f19dd8f 100644 --- a/src/wrapped/wrappedsmime3.c +++ b/src/wrapped/wrappedsmime3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmpeg.c b/src/wrapped/wrappedsmpeg.c index f5242dbda..58a408d89 100644 --- a/src/wrapped/wrappedsmpeg.c +++ b/src/wrapped/wrappedsmpeg.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsmpeg2.c b/src/wrapped/wrappedsmpeg2.c index 0c06c9169..6985a7383 100644 --- a/src/wrapped/wrappedsmpeg2.c +++ b/src/wrapped/wrappedsmpeg2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsoftokn3.c b/src/wrapped/wrappedsoftokn3.c index 5115a3f78..feee9554f 100644 --- a/src/wrapped/wrappedsoftokn3.c +++ b/src/wrapped/wrappedsoftokn3.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped/wrappedssh4.c b/src/wrapped/wrappedssh4.c index 6c9a1757a..4613f7c7d 100644 --- a/src/wrapped/wrappedssh4.c +++ b/src/wrapped/wrappedssh4.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedssl3.c b/src/wrapped/wrappedssl3.c index 0f61b6f51..481a01b4d 100644 --- a/src/wrapped/wrappedssl3.c +++ b/src/wrapped/wrappedssl3.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedsystemd.c b/src/wrapped/wrappedsystemd.c index edb90fe77..ce9d94229 100644 --- a/src/wrapped/wrappedsystemd.c +++ b/src/wrapped/wrappedsystemd.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtbbbind.c b/src/wrapped/wrappedtbbbind.c index cf8f94e74..0ba838c9e 100644 --- a/src/wrapped/wrappedtbbbind.c +++ b/src/wrapped/wrappedtbbbind.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtbbmalloc.c b/src/wrapped/wrappedtbbmalloc.c index f3563a16f..822c65af0 100644 --- a/src/wrapped/wrappedtbbmalloc.c +++ b/src/wrapped/wrappedtbbmalloc.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtbbmallocproxy.c b/src/wrapped/wrappedtbbmallocproxy.c index 78ee5e7b1..fb803969f 100644 --- a/src/wrapped/wrappedtbbmallocproxy.c +++ b/src/wrapped/wrappedtbbmallocproxy.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtcmallocminimal.c b/src/wrapped/wrappedtcmallocminimal.c index cd1ed3ea2..f1912ac57 100644 --- a/src/wrapped/wrappedtcmallocminimal.c +++ b/src/wrapped/wrappedtcmallocminimal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedtermuxexec.c b/src/wrapped/wrappedtermuxexec.c index 0fdf9f110..f7fcdda42 100644 --- a/src/wrapped/wrappedtermuxexec.c +++ b/src/wrapped/wrappedtermuxexec.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedudev0.c b/src/wrapped/wrappedudev0.c index 65eba557c..cf7aecb60 100644 --- a/src/wrapped/wrappedudev0.c +++ b/src/wrapped/wrappedudev0.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedudev1.c b/src/wrapped/wrappedudev1.c index 57304fe96..58da26349 100644 --- a/src/wrapped/wrappedudev1.c +++ b/src/wrapped/wrappedudev1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedunwind.c b/src/wrapped/wrappedunwind.c index aae8965a1..fa99bb80c 100644 --- a/src/wrapped/wrappedunwind.c +++ b/src/wrapped/wrappedunwind.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped/wrappedutil.c b/src/wrapped/wrappedutil.c index 456a79b5d..8d09a6dd6 100644 --- a/src/wrapped/wrappedutil.c +++ b/src/wrapped/wrappedutil.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedvorbisfile.c b/src/wrapped/wrappedvorbisfile.c index 721b59d47..4a86f84ba 100644 --- a/src/wrapped/wrappedvorbisfile.c +++ b/src/wrapped/wrappedvorbisfile.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedvulkan.c b/src/wrapped/wrappedvulkan.c index adf0b938d..a88d7e30f 100644 --- a/src/wrapped/wrappedvulkan.c +++ b/src/wrapped/wrappedvulkan.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedvulkan_private.h b/src/wrapped/wrappedvulkan_private.h index b6e466b3e..6d751c6d7 100644 --- a/src/wrapped/wrappedvulkan_private.h +++ b/src/wrapped/wrappedvulkan_private.h @@ -1179,6 +1179,9 @@ GO(vkCmdBeginCustomResolveEXT, vFpp) // VK_NV_compute_occupancy_priority GO(vkCmdSetComputeOccupancyPriorityNV, vFpp) +// VK_EXT_cooperative_matrix_maintenance1 +GO(vkGetPhysicalDeviceCooperativeMatrixProperties2EXT, iFpppp) + // Layer stuffs GO(vk_icdNegotiateLoaderICDInterfaceVersion, iFp) //GO(vkNegotiateLoaderLayerInterfaceVersion, iFp) diff --git a/src/wrapped/wrappedwaylandclient.c b/src/wrapped/wrappedwaylandclient.c index ae548714c..1bf5f4185 100644 --- a/src/wrapped/wrappedwaylandclient.c +++ b/src/wrapped/wrappedwaylandclient.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include @@ -75,6 +74,29 @@ static void* find_wl_log_func_t_Fct(void* fct) return NULL; } +//wl_dispatcher_func_t +#define GO(A) \ +static uintptr_t my_wl_dispatcher_func_t_fct_##A = 0; \ +static int my_wl_dispatcher_func_t_##A(const void* user_data, void* target, uint32_t opcode, const void* msg, void* args) \ +{ \ + return (int)RunFunctionFmt(my_wl_dispatcher_func_t_fct_##A, "ppupp", user_data, target, opcode, msg, args); \ +} +SUPER() +#undef GO +static void* find_wl_dispatcher_func_t_Fct(void* fct) +{ + if(!fct) return fct; + if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct); + #define GO(A) if(my_wl_dispatcher_func_t_fct_##A == (uintptr_t)fct) return my_wl_dispatcher_func_t_##A; + SUPER() + #undef GO + #define GO(A) if(my_wl_dispatcher_func_t_fct_##A == 0) {my_wl_dispatcher_func_t_fct_##A = (uintptr_t)fct; return my_wl_dispatcher_func_t_##A; } + SUPER() + #undef GO + printf_log(LOG_NONE, "Warning, no more slot for wayland-client wl_dispatcher_func_t callback\n"); + return NULL; +} + // wl_registry_listener ... typedef struct my_wl_registry_listener_s { uintptr_t global; //vFppupu @@ -1634,6 +1656,12 @@ static void* find_gtk_surface1_listener_Fct(void* fct) } #undef SUPER +EXPORT int my_wl_proxy_add_dispatcher(x64emu_t* emu, void* proxy, void* dispatcher_func, void* dispatcher_data, void* data) +{ + if (!proxy) return -1; + return my->wl_proxy_add_dispatcher(proxy, find_wl_dispatcher_func_t_Fct(dispatcher_func), dispatcher_data, data); +} + EXPORT int my_wl_proxy_add_listener(x64emu_t* emu, void* proxy, void** l, void* data) { if (!proxy) return -1; diff --git a/src/wrapped/wrappedwaylandclient_private.h b/src/wrapped/wrappedwaylandclient_private.h index 9a3b2a6fa..e02998cd1 100644 --- a/src/wrapped/wrappedwaylandclient_private.h +++ b/src/wrapped/wrappedwaylandclient_private.h @@ -45,7 +45,7 @@ GO(wl_list_remove, vFp) GOM(wl_log_set_handler_client, vFEp) DATA(wl_output_interface, 40) DATA(wl_pointer_interface, 40) -//GOM(wl_proxy_add_dispatcher, iFEpppp) +GOM(wl_proxy_add_dispatcher, iFEpppp) GOM(wl_proxy_add_listener, iFEppp) GO(wl_proxy_create, pFpp) GO(wl_proxy_create_wrapper, pFp) diff --git a/src/wrapped/wrappedwaylandcursor.c b/src/wrapped/wrappedwaylandcursor.c index fa2ad8b5f..e2fcd06d6 100644 --- a/src/wrapped/wrappedwaylandcursor.c +++ b/src/wrapped/wrappedwaylandcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedwaylandegl.c b/src/wrapped/wrappedwaylandegl.c index 57da6b275..316614639 100644 --- a/src/wrapped/wrappedwaylandegl.c +++ b/src/wrapped/wrappedwaylandegl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxinerama.c b/src/wrapped/wrappedxinerama.c index c83211a35..9ddf458ce 100644 --- a/src/wrapped/wrappedxinerama.c +++ b/src/wrapped/wrappedxinerama.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbcommon.c b/src/wrapped/wrappedxkbcommon.c index 96c0d4aab..845163df7 100644 --- a/src/wrapped/wrappedxkbcommon.c +++ b/src/wrapped/wrappedxkbcommon.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbcommonx11.c b/src/wrapped/wrappedxkbcommonx11.c index 91aa6d5b9..1546c9919 100644 --- a/src/wrapped/wrappedxkbcommonx11.c +++ b/src/wrapped/wrappedxkbcommonx11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbfile.c b/src/wrapped/wrappedxkbfile.c index 7b5130e6d..04c9c418a 100644 --- a/src/wrapped/wrappedxkbfile.c +++ b/src/wrapped/wrappedxkbfile.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxkbregistry.c b/src/wrapped/wrappedxkbregistry.c index 957fc2848..81579623d 100644 --- a/src/wrapped/wrappedxkbregistry.c +++ b/src/wrapped/wrappedxkbregistry.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxml2.c b/src/wrapped/wrappedxml2.c index 799e63676..26e9aece4 100644 --- a/src/wrapped/wrappedxml2.c +++ b/src/wrapped/wrappedxml2.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped/wrappedxshmfence.c b/src/wrapped/wrappedxshmfence.c index 8baad58a5..3b45991f5 100644 --- a/src/wrapped/wrappedxshmfence.c +++ b/src/wrapped/wrappedxshmfence.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedxslt.c b/src/wrapped/wrappedxslt.c index e9dbb6ce9..fe299d6b6 100644 --- a/src/wrapped/wrappedxslt.c +++ b/src/wrapped/wrappedxslt.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped/wrappedzstd.c b/src/wrapped/wrappedzstd.c index d0495f4db..fdb016466 100644 --- a/src/wrapped/wrappedzstd.c +++ b/src/wrapped/wrappedzstd.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedblkid.c b/src/wrapped32/wrappedblkid.c index 5e007e5a1..8edad5e42 100644 --- a/src/wrapped32/wrappedblkid.c +++ b/src/wrapped32/wrappedblkid.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedcairo.c b/src/wrapped32/wrappedcairo.c index 389a68825..c93512b55 100644 --- a/src/wrapped32/wrappedcairo.c +++ b/src/wrapped32/wrappedcairo.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedcurl.c b/src/wrapped32/wrappedcurl.c index 82fc7676c..af0471254 100644 --- a/src/wrapped32/wrappedcurl.c +++ b/src/wrapped32/wrappedcurl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappeddbus.c b/src/wrapped32/wrappeddbus.c index fc12e41eb..2f3a9983e 100644 --- a/src/wrapped32/wrappeddbus.c +++ b/src/wrapped32/wrappeddbus.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedexpat.c b/src/wrapped32/wrappedexpat.c index 5c7a7865f..b190d5236 100644 --- a/src/wrapped32/wrappedexpat.c +++ b/src/wrapped32/wrappedexpat.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedfontconfig.c b/src/wrapped32/wrappedfontconfig.c index c88b1a932..d0bd6cbeb 100644 --- a/src/wrapped32/wrappedfontconfig.c +++ b/src/wrapped32/wrappedfontconfig.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedfreetype.c b/src/wrapped32/wrappedfreetype.c index f7e0f26bf..702d876a4 100644 --- a/src/wrapped32/wrappedfreetype.c +++ b/src/wrapped32/wrappedfreetype.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedgbm.c b/src/wrapped32/wrappedgbm.c index cb8f54963..2ffaa6f04 100644 --- a/src/wrapped32/wrappedgbm.c +++ b/src/wrapped32/wrappedgbm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedgnutls.c b/src/wrapped32/wrappedgnutls.c index ac7cfbb39..b48a55b02 100644 --- a/src/wrapped32/wrappedgnutls.c +++ b/src/wrapped32/wrappedgnutls.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedldlinux.c b/src/wrapped32/wrappedldlinux.c index 869d60d9f..355af9f7e 100755 --- a/src/wrapped32/wrappedldlinux.c +++ b/src/wrapped32/wrappedldlinux.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibasound.c b/src/wrapped32/wrappedlibasound.c index f001b2e1d..ebc280c45 100644 --- a/src/wrapped32/wrappedlibasound.c +++ b/src/wrapped32/wrappedlibasound.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index ae0af7f56..e420f91c9 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include @@ -49,6 +48,7 @@ #endif #include #include +#include #include "wrappedlibs.h" @@ -207,7 +207,7 @@ struct i386_stat { uint32_t __unused5; } __attribute__((packed)); -static int FillStatFromStat64(int vers, const struct stat64 *st64, void *st32) +static int FillStatFromStat64(int vers, const struct stat *st64, void *st32) { struct i386_stat *i386st = (struct i386_stat *)st32; @@ -434,7 +434,7 @@ static void* findgloberrFct(void* fct) // filter_dir #define GO(A) \ static uintptr_t my32_filter_dir_fct_##A = 0; \ -static int my32_filter_dir_##A(const struct dirent64* a) \ +static int my32_filter_dir_##A(const struct dirent* a) \ { \ static struct i386_dirent d = {0}; \ UnalignDirent_32(a, &d); \ @@ -473,7 +473,7 @@ static void* findcompare_dirFct(void* fct) { if(!fct) return NULL; void* p; - if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort64; else return p; } + if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort; else return p; } #define GO(A) if(my32_compare_dir_fct_##A == (uintptr_t)fct) return my32_compare_dir_##A; SUPER() #undef GO @@ -486,7 +486,7 @@ static void* findcompare_dirFct(void* fct) // filter64 #define GO(A) \ static uintptr_t my32_filter64_fct_##A = 0; \ -static int my32_filter64_##A(const struct dirent64* a) \ +static int my32_filter64_##A(const struct dirent* a) \ { \ return (int)RunFunctionFmt(my32_filter64_fct_##A, "p", a); \ } @@ -509,7 +509,7 @@ static void* findfilter64Fct(void* fct) // compare64 #define GO(A) \ static uintptr_t my32_compare64_fct_##A = 0; \ -static int my32_compare64_##A(const struct dirent64* a, const struct dirent64* b) \ +static int my32_compare64_##A(const struct dirent* a, const struct dirent* b) \ { \ return (int)RunFunctionFmt(my32_compare64_fct_##A, "pp", a, b); \ } @@ -519,7 +519,7 @@ static void* findcompare64Fct(void* fct) { if(!fct) return NULL; void* p; - if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort64; else return p; } + if((p = GetNativeFnc((uintptr_t)fct))) { if(p==my32_alphasort64) return alphasort; else return p; } #define GO(A) if(my32_compare64_fct_##A == (uintptr_t)fct) return my32_compare64_##A; SUPER() #undef GO @@ -598,9 +598,9 @@ EXPORT int my32_fstatvfs(x64emu_t* emu, int fd, void* r) EXPORT int my32_fstatat(x64emu_t* emu, int fd, void* name, void* buff, int flags) { - struct stat64 s = {0}; - struct stat64* p = buff?&s:NULL; - int ret = fstatat64(fd, name, p, flags); + struct stat s = {0}; + struct stat* p = buff?&s:NULL; + int ret = fstatat(fd, name, p, flags); if(buff) FillStatFromStat64(3, &s, buff); return ret; @@ -608,9 +608,9 @@ EXPORT int my32_fstatat(x64emu_t* emu, int fd, void* name, void* buff, int flags EXPORT int my32_fstatat64(x64emu_t* emu, int fd, void* name, void* buff, int flags) { - struct stat64 s = {0}; - struct stat64* p = buff?&s:NULL; - int ret = fstatat64(fd, name, p, flags); + struct stat s = {0}; + struct stat* p = buff?&s:NULL; + int ret = fstatat(fd, name, p, flags); if(buff) UnalignStat64_32(&s, buff); return ret; @@ -618,9 +618,9 @@ EXPORT int my32_fstatat64(x64emu_t* emu, int fd, void* name, void* buff, int fla EXPORT int my32___stat64_time64(x64emu_t* emu, void* f, void* r) { - struct stat64 s = {0}; - struct stat64* p = r?&s:NULL; - int ret = stat64(f, p); + struct stat s = {0}; + struct stat* p = r?&s:NULL; + int ret = stat(f, p); if(r) UnalignStat64_32_t64(&s, r); return ret; @@ -628,9 +628,9 @@ EXPORT int my32___stat64_time64(x64emu_t* emu, void* f, void* r) EXPORT int my32___lstat64_time64(x64emu_t* emu, void* f, void* r) { - struct stat64 s = {0}; - struct stat64* p = r?&s:NULL; - int ret = lstat64(f, p); + struct stat s = {0}; + struct stat* p = r?&s:NULL; + int ret = lstat(f, p); if(r) UnalignStat64_32_t64(&s, r); return ret; @@ -638,9 +638,9 @@ EXPORT int my32___lstat64_time64(x64emu_t* emu, void* f, void* r) EXPORT int my32___fstat64_time64(x64emu_t* emu, int fd, void* r) { - struct stat64 s = {0}; - struct stat64* p = r?&s:NULL; - int ret = fstat64(fd, p); + struct stat s = {0}; + struct stat* p = r?&s:NULL; + int ret = fstat(fd, p); if(r) UnalignStat64_32_t64(&s, r); return ret; @@ -1230,32 +1230,32 @@ EXPORT void my32__ITM_deregisterTMCloneTable(x64emu_t* emu, void* p) {} EXPORT int my32_stat(char* path, void* buf) { - struct stat64 st; - int r = stat64(path, &st); + struct stat st; + int r = stat(path, &st); FillStatFromStat64(3, &st, buf); return r; } EXPORT int my32_fstat(int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); FillStatFromStat64(3, &st, buf); return r; } EXPORT int my32_lstat(char* path, void* buf) { - struct stat64 st; - int r = lstat64(path, &st); + struct stat st; + int r = lstat(path, &st); FillStatFromStat64(3, &st, buf); return r; } EXPORT int my32___fxstat(x64emu_t *emu, int vers, int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); if (r) return r; r = FillStatFromStat64(vers, &st, buf); return r; @@ -1263,8 +1263,8 @@ EXPORT int my32___fxstat(x64emu_t *emu, int vers, int fd, void* buf) EXPORT int my32___fxstat64(x64emu_t *emu, int vers, int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); //int r = syscall(__NR_stat64, fd, &st); UnalignStat64_32(&st, buf); return r; @@ -1293,30 +1293,30 @@ EXPORT int my32_statx(x64emu_t* emu, int dirfd, void* path, int flags, uint32_t EXPORT int my32_stat64(void* path, void* buf) { - struct stat64 st; - int r = stat64(path, &st); + struct stat st; + int r = stat(path, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32_lstat64(void* path, void* buf) { - struct stat64 st; - int r = lstat64(path, &st); + struct stat st; + int r = lstat(path, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32_fstat64(int fd, void* buf) { - struct stat64 st; - int r = fstat64(fd, &st); + struct stat st; + int r = fstat(fd, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32___xstat(x64emu_t* emu, int v, void* path, void* buf) { - struct stat64 st; - int r = stat64((const char*)path, &st); + struct stat st; + int r = stat((const char*)path, &st); if (r) return r; r = FillStatFromStat64(v, &st, buf); return r; @@ -1324,16 +1324,16 @@ EXPORT int my32___xstat(x64emu_t* emu, int v, void* path, void* buf) EXPORT int my32___xstat64(x64emu_t* emu, int v, void* path, void* buf) { - struct stat64 st; - int r = stat64((const char*)path, &st); + struct stat st; + int r = stat((const char*)path, &st); UnalignStat64_32(&st, buf); return r; } EXPORT int my32___lxstat(x64emu_t* emu, int v, void* name, void* buf) { - struct stat64 st; - int r = lstat64((const char*)name, &st); + struct stat st; + int r = lstat((const char*)name, &st); if (r) return r; r = FillStatFromStat64(v, &st, buf); return r; @@ -1341,16 +1341,16 @@ EXPORT int my32___lxstat(x64emu_t* emu, int v, void* name, void* buf) EXPORT int my32___lxstat64(x64emu_t* emu, int v, void* name, void* buf) { - struct stat64 st; - int r = lstat64((const char*)name, &st); + struct stat st; + int r = lstat((const char*)name, &st); UnalignStat64_32(&st, buf); return r; } #if 0 EXPORT int my32___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, int flags) { - struct stat64 st; - int r = fstatat64(d, path, &st, flags); + struct stat st; + int r = fstatat(d, path, &st, flags); if (r) return r; r = FillStatFromStat64(v, &st, buf); return r; @@ -1358,15 +1358,15 @@ EXPORT int my32___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, i #endif EXPORT int my32___fxstatat64(x64emu_t* emu, int v, int d, void* path, void* buf, int flags) { - struct stat64 st; - int r = fstatat64(d, path, &st, flags); + struct stat st; + int r = fstatat(d, path, &st, flags); UnalignStat64_32(&st, buf); return r; } #if 0 EXPORT int my32__IO_file_stat(x64emu_t* emu, void* f, void* buf) { - struct stat64 st; + struct stat st; libc_my32_t *my = (libc_my32_t *)emu->context->libclib->priv.w.p2; int r = my->_IO_file_stat(f, &st); UnalignStat64(&st, buf); @@ -1375,30 +1375,30 @@ EXPORT int my32__IO_file_stat(x64emu_t* emu, void* f, void* buf) #endif EXPORT int my32_fstatfs(int fd, void* buf) { - struct statfs64 st; - int r = fstatfs64(fd, &st); + struct statfs st; + int r = fstatfs(fd, &st); UnalignStatFS_32(&st, buf); return r; } EXPORT int my32_fstatfs64(int fd, void* buf) { - struct statfs64 st; - int r = fstatfs64(fd, &st); + struct statfs st; + int r = fstatfs(fd, &st); UnalignStatFS64_32(&st, buf); return r; } EXPORT int my32_statfs(const char* path, void* buf) { - struct statfs64 st; - int r = statfs64(path, &st); + struct statfs st; + int r = statfs(path, &st); UnalignStatFS_32(&st, buf); return r; } EXPORT int my32_statfs64(const char* path, void* buf) { - struct statfs64 st; - int r = statfs64(path, &st); + struct statfs st; + int r = statfs(path, &st); UnalignStatFS64_32(&st, buf); return r; } @@ -1497,7 +1497,7 @@ EXPORT void* my32_fts_open(x64emu_t* emu, void* path, int options, void* c) EXPORT void* my32_readdir(x64emu_t* emu, void* dirp) { - struct dirent64 *dp64 = readdir64((DIR *)dirp); + struct dirent *dp64 = readdir((DIR *)dirp); if (!dp64) return NULL; static struct i386_dirent dp32 = {0}; uint32_t ino32 = dp64->d_ino ^ (dp64->d_ino >> 32); @@ -1513,7 +1513,7 @@ EXPORT void* my32_readdir(x64emu_t* emu, void* dirp) EXPORT int32_t my32_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** result) { - struct dirent64 d64, *dp64; + struct dirent d64, *dp64; if (BOX64ENV(fix_64bit_inodes) && (sizeof(d64.d_name) > 1)) { static iFppp_t f = NULL; @@ -1524,7 +1524,7 @@ EXPORT int32_t my32_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** res *result = NULL; return 0; } - f = (iFppp_t)dlsym(lib->priv.w.lib, "readdir64_r"); + f = (iFppp_t)dlsym(lib->priv.w.lib, "readdir_r"); } int r = f(dirp, &d64, &dp64); @@ -1535,7 +1535,7 @@ EXPORT int32_t my32_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** res } struct i386_dirent *dp32 = (struct i386_dirent *)entry; - int namelen = dp64->d_reclen - offsetof(struct dirent64, d_name); + int namelen = dp64->d_reclen - offsetof(struct dirent, d_name); if (namelen > sizeof(dp32->d_name)) { *result = NULL; @@ -1695,18 +1695,18 @@ EXPORT int my32_mkstemps64(x64emu_t* emu, char* template, int suffixlen) sprintf(num, "%06d", rand()%999999); memcpy(fname+strlen(fname)-suffixlen-6, num, 6); } while(!FileExist(fname, -1)); - int ret = open64(fname, O_EXCL); + int ret = open(fname, O_EXCL); free(fname); return ret; } EXPORT int32_t my32_ftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd) { - return ftw64(pathname, findftwFct(B), nopenfd); + return ftw(pathname, findftwFct(B), nopenfd); } EXPORT int32_t my32_nftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) { - return nftw64(pathname, findnftwFct(B), nopenfd, flags); + return nftw(pathname, findnftwFct(B), nopenfd, flags); } EXPORT void* my32_ldiv(x64emu_t* emu, void* p, int32_t num, int32_t den) @@ -1752,7 +1752,7 @@ typedef struct my_glob_32_s ptr_t gl_lstat; //int (*gl_lstat) (const char *__restrict, struct stat *__restrict); ptr_t gl_stat; //int (*gl_stat) (const char *__restrict, struct stat *__restrict); } my_glob_32_t; -// glob64 is identical, except function are 64bits versions +// glob is identical, except function are 64bits versions static void convert_glob_to_32(void* d, void* s, int is64) { @@ -1783,54 +1783,54 @@ static void convert_glob_to_64(void* d, void* s, int is64) EXPORT int32_t my32_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; if(flags & GLOB_ALTDIRFUNC) printf_log(LOG_NONE, "Error: using unsupport GLOB_ALTDIRFUNC in glob\n"); if(flags&(1<<5)) // GLOB_APPEND is used, so convert also before convert_glob_to_64(&glob_l, pglob, 0); - int ret = glob64(pat, flags, findgloberrFct(errfnc), &glob_l); + int ret = glob(pat, flags, findgloberrFct(errfnc), &glob_l); convert_glob_to_32(pglob, &glob_l, 0); return ret; } EXPORT void my32_globfree(x64emu_t* emu, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; convert_glob_to_64(&glob_l, pglob, 0); - globfree64(&glob_l); + globfree(&glob_l); } #ifndef ANDROID EXPORT int32_t my32_glob64(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; if(flags & GLOB_ALTDIRFUNC) printf_log(LOG_NONE, "Error: using unsupport GLOB_ALTDIRFUNC in glob64\n"); if(flags&(1<<5)) // GLOB_APPEND is used, so convert also before convert_glob_to_64(&glob_l, pglob, 1); - int ret = glob64(pat, flags, findgloberrFct(errfnc), &glob_l); + int ret = glob(pat, flags, findgloberrFct(errfnc), &glob_l); convert_glob_to_32(pglob, &glob_l, 1); return ret; } EXPORT void my32_globfree64(x64emu_t* emu, void* pglob) { - glob64_t glob_l = {0}; + glob_t glob_l = {0}; convert_glob_to_64(&glob_l, pglob, 1); - globfree64(&glob_l); + globfree(&glob_l); } #endif EXPORT int my32_scandir(x64emu_t *emu, void* dir, ptr_t* namelist, void* sel, void* comp) { - struct dirent64** list = NULL; - int ret = scandir64(dir, &list, findfilter_dirFct(sel), findcompare_dirFct(comp)); + struct dirent** list = NULL; + int ret = scandir(dir, &list, findfilter_dirFct(sel), findcompare_dirFct(comp)); *namelist = to_ptrv(list); if (ret>0) { // adjust the array of dirent... inplace adjust of listname and inplace of dirent too for(int i=0; id_ino ^ (dp64->d_ino >> 32); int32_t off32 = dp64->d_off; dp32->d_ino = ino32; dp32->d_off = off32; - dp32->d_reclen = dp64->d_reclen-(offsetof(struct dirent64, d_name)-offsetof(struct i386_dirent, d_name)); + dp32->d_reclen = dp64->d_reclen-(offsetof(struct dirent, d_name)-offsetof(struct i386_dirent, d_name)); dp32->d_type = dp64->d_type; memmove(dp32->d_name, dp64->d_name, dp32->d_reclen-offsetof(struct i386_dirent, d_name)); // inplace shrink pointer to @@ -1841,8 +1841,8 @@ EXPORT int my32_scandir(x64emu_t *emu, void* dir, ptr_t* namelist, void* sel, vo } EXPORT int my32_scandir64(x64emu_t *emu, void* dir, ptr_t* namelist, void* sel, void* comp) { - struct dirent64** list; - int ret = scandir64(dir, &list, findfilter64Fct(sel), findcompare64Fct(comp)); + struct dirent** list; + int ret = scandir(dir, &list, findfilter64Fct(sel), findcompare64Fct(comp)); if(ret>=0) *namelist = to_ptrv(list); if (ret>0) { @@ -1898,12 +1898,12 @@ EXPORT long my32_readv(x64emu_t* emu, int fd, struct i386_iovec* iov, int niov) EXPORT int my32_ftw64(x64emu_t* emu, void* filename, void* func, int descriptors) { - return ftw64(filename, findftw64Fct(func), descriptors); + return ftw(filename, findftw64Fct(func), descriptors); } EXPORT int32_t my32_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags) { - return nftw64(pathname, findnftw64Fct(B), nopenfd, flags); + return nftw(pathname, findnftw64Fct(B), nopenfd, flags); } EXPORT ptr_t my32_environ = 0; //char** @@ -2370,8 +2370,8 @@ EXPORT unsigned long int my32___fdelt_chk (unsigned long int d) EXPORT int my32_getrlimit(x64emu_t* emu, int what, uint32_t* pr) { - struct rlimit64 l = {0}; - int ret = getrlimit64(what, &l); + struct rlimit l = {0}; + int ret = getrlimit(what, &l); if(pr) { pr[0] = (l.rlim_cur<0x100000000LL)?l.rlim_cur:0xffffffff; pr[1] = (l.rlim_max<0x100000000LL)?l.rlim_max:0xffffffff; @@ -2380,10 +2380,10 @@ EXPORT int my32_getrlimit(x64emu_t* emu, int what, uint32_t* pr) } EXPORT int my32_setrlimit(x64emu_t* emu, int what, uint32_t* pr) { - struct rlimit64 l = {0}; + struct rlimit l = {0}; l.rlim_cur = (pr[0]!=0xffffffff)?pr[0]:0xffffffffffffffffLL; l.rlim_max = (pr[1]!=0xffffffff)?pr[1]:0xffffffffffffffffLL; - return setrlimit64(what, &l); + return setrlimit(what, &l); } EXPORT void* my32___localtime64(x64emu_t* emu, void* t) @@ -2788,13 +2788,13 @@ EXPORT int my32_getopt_long_only(int argc, char* const argv[], const char* optst EXPORT int my32_alphasort64(x64emu_t* emu, ptr_t* d1_, ptr_t* d2_) { - const struct dirent64* d1 = NULL; - const struct dirent64* d2 = NULL; - if(d1_) d1 = (struct dirent64*)from_ptrv(*d1_); - if(d2_) d2 = (struct dirent64*)from_ptrv(*d2_); - const struct dirent64** e1 = d1_?(&d1):NULL; - const struct dirent64** e2 = d2_?(&d2):NULL; - return alphasort64(e1, e2); + const struct dirent* d1 = NULL; + const struct dirent* d2 = NULL; + if(d1_) d1 = (struct dirent*)from_ptrv(*d1_); + if(d2_) d2 = (struct dirent*)from_ptrv(*d2_); + const struct dirent** e1 = d1_?(&d1):NULL; + const struct dirent** e2 = d2_?(&d2):NULL; + return alphasort(e1, e2); } #ifndef ANDROID @@ -3202,7 +3202,7 @@ static ssize_t my32_cookie_write(void *p, const char *buf, size_t size) my32_cookie_t* cookie = (my32_cookie_t*)p; return (ssize_t)RunFunction(my_context, cookie->w, 3, cookie->cookie, buf, size); } -static int my32_cookie_seek(void *p, off64_t *offset, int whence) +static int my32_cookie_seek(void *p, off_t *offset, int whence) { my32_cookie_t* cookie = (my32_cookie_t*)p; return RunFunction(my_context, cookie->s, 3, cookie->cookie, offset, whence); diff --git a/src/wrapped32/wrappedlibcups.c b/src/wrapped32/wrappedlibcups.c index 9ede52102..4b49afe71 100644 --- a/src/wrapped32/wrappedlibcups.c +++ b/src/wrapped32/wrappedlibcups.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibdl.c b/src/wrapped32/wrappedlibdl.c index 12039ad6f..379f588fc 100755 --- a/src/wrapped32/wrappedlibdl.c +++ b/src/wrapped32/wrappedlibdl.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibdrm.c b/src/wrapped32/wrappedlibdrm.c index d414763fe..55cb943d1 100644 --- a/src/wrapped32/wrappedlibdrm.c +++ b/src/wrapped32/wrappedlibdrm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibegl.c b/src/wrapped32/wrappedlibegl.c index 3f72233ca..2e96e9027 100644 --- a/src/wrapped32/wrappedlibegl.c +++ b/src/wrapped32/wrappedlibegl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibgl.c b/src/wrapped32/wrappedlibgl.c index 06ad51e00..875c3a504 100644 --- a/src/wrapped32/wrappedlibgl.c +++ b/src/wrapped32/wrappedlibgl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibglu.c b/src/wrapped32/wrappedlibglu.c index 8558648d6..c8aa21eba 100644 --- a/src/wrapped32/wrappedlibglu.c +++ b/src/wrapped32/wrappedlibglu.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibglx.c b/src/wrapped32/wrappedlibglx.c index 305fd8478..76ce612cf 100644 --- a/src/wrapped32/wrappedlibglx.c +++ b/src/wrapped32/wrappedlibglx.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibglxnvidia.c b/src/wrapped32/wrappedlibglxnvidia.c index e5e8a23c1..b0543864b 100644 --- a/src/wrapped32/wrappedlibglxnvidia.c +++ b/src/wrapped32/wrappedlibglxnvidia.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibm.c b/src/wrapped32/wrappedlibm.c index dd0a6ab37..07bda89ab 100755 --- a/src/wrapped32/wrappedlibm.c +++ b/src/wrapped32/wrappedlibm.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include diff --git a/src/wrapped32/wrappedlibogg.c b/src/wrapped32/wrappedlibogg.c index 877b03853..1c32ebde5 100644 --- a/src/wrapped32/wrappedlibogg.c +++ b/src/wrapped32/wrappedlibogg.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibpthread.c b/src/wrapped32/wrappedlibpthread.c index 7c477c57a..1640580ad 100755 --- a/src/wrapped32/wrappedlibpthread.c +++ b/src/wrapped32/wrappedlibpthread.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped32/wrappedlibresolv.c b/src/wrapped32/wrappedlibresolv.c index cc0630564..0f4af9ebe 100644 --- a/src/wrapped32/wrappedlibresolv.c +++ b/src/wrapped32/wrappedlibresolv.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedlibrt.c b/src/wrapped32/wrappedlibrt.c index 0a72043d0..66e12e8d6 100755 --- a/src/wrapped32/wrappedlibrt.c +++ b/src/wrapped32/wrappedlibrt.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE #include #include #include diff --git a/src/wrapped32/wrappedlibuuid.c b/src/wrapped32/wrappedlibuuid.c index df5f67fa3..55c79094a 100644 --- a/src/wrapped32/wrappedlibuuid.c +++ b/src/wrapped32/wrappedlibuuid.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibvdpau.c b/src/wrapped32/wrappedlibvdpau.c index 5675e113d..da26c211e 100644 --- a/src/wrapped32/wrappedlibvdpau.c +++ b/src/wrapped32/wrappedlibvdpau.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibvorbis.c b/src/wrapped32/wrappedlibvorbis.c index e3d05c1b6..d86eaaeae 100644 --- a/src/wrapped32/wrappedlibvorbis.c +++ b/src/wrapped32/wrappedlibvorbis.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibx11.c b/src/wrapped32/wrappedlibx11.c index 34d5be1c9..71053b2ca 100644 --- a/src/wrapped32/wrappedlibx11.c +++ b/src/wrapped32/wrappedlibx11.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibx11xcb.c b/src/wrapped32/wrappedlibx11xcb.c index be3cfc4a3..e58f04462 100644 --- a/src/wrapped32/wrappedlibx11xcb.c +++ b/src/wrapped32/wrappedlibx11xcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcb.c b/src/wrapped32/wrappedlibxcb.c index 4b676b7c8..d070f9020 100644 --- a/src/wrapped32/wrappedlibxcb.c +++ b/src/wrapped32/wrappedlibxcb.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcbres.c b/src/wrapped32/wrappedlibxcbres.c index 8bffcf265..863702e25 100644 --- a/src/wrapped32/wrappedlibxcbres.c +++ b/src/wrapped32/wrappedlibxcbres.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcomposite.c b/src/wrapped32/wrappedlibxcomposite.c index 38dd96035..eb5ca3411 100644 --- a/src/wrapped32/wrappedlibxcomposite.c +++ b/src/wrapped32/wrappedlibxcomposite.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxcursor.c b/src/wrapped32/wrappedlibxcursor.c index e0762b9ca..8f714a9c1 100644 --- a/src/wrapped32/wrappedlibxcursor.c +++ b/src/wrapped32/wrappedlibxcursor.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxdamage.c b/src/wrapped32/wrappedlibxdamage.c index 0b1520c60..98ce3fb8e 100644 --- a/src/wrapped32/wrappedlibxdamage.c +++ b/src/wrapped32/wrappedlibxdamage.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxext.c b/src/wrapped32/wrappedlibxext.c index e26b0cc08..a9c7d2a99 100644 --- a/src/wrapped32/wrappedlibxext.c +++ b/src/wrapped32/wrappedlibxext.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxfixes.c b/src/wrapped32/wrappedlibxfixes.c index 510482a9a..dfbb3a928 100644 --- a/src/wrapped32/wrappedlibxfixes.c +++ b/src/wrapped32/wrappedlibxfixes.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxi.c b/src/wrapped32/wrappedlibxi.c index 211f1fbeb..9dd4074bb 100644 --- a/src/wrapped32/wrappedlibxi.c +++ b/src/wrapped32/wrappedlibxi.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxrandr.c b/src/wrapped32/wrappedlibxrandr.c index 6ef7c7776..ea6f2a631 100644 --- a/src/wrapped32/wrappedlibxrandr.c +++ b/src/wrapped32/wrappedlibxrandr.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxrender.c b/src/wrapped32/wrappedlibxrender.c index 63702b647..c21fc5a9c 100644 --- a/src/wrapped32/wrappedlibxrender.c +++ b/src/wrapped32/wrappedlibxrender.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxss.c b/src/wrapped32/wrappedlibxss.c index 5598da659..db173c341 100644 --- a/src/wrapped32/wrappedlibxss.c +++ b/src/wrapped32/wrappedlibxss.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedlibxxf86vm.c b/src/wrapped32/wrappedlibxxf86vm.c index d3d1ea498..dd1d60c08 100644 --- a/src/wrapped32/wrappedlibxxf86vm.c +++ b/src/wrapped32/wrappedlibxxf86vm.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedmount.c b/src/wrapped32/wrappedmount.c index 7b70b1dd3..a530afa9a 100644 --- a/src/wrapped32/wrappedmount.c +++ b/src/wrapped32/wrappedmount.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappednsl.c b/src/wrapped32/wrappednsl.c index d410a31cc..fbe931cfb 100644 --- a/src/wrapped32/wrappednsl.c +++ b/src/wrapped32/wrappednsl.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappednvml.c b/src/wrapped32/wrappednvml.c index e45ac7b88..b52cc178c 100644 --- a/src/wrapped32/wrappednvml.c +++ b/src/wrapped32/wrappednvml.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedopenal.c b/src/wrapped32/wrappedopenal.c index c3ae726e8..5cacb9655 100644 --- a/src/wrapped32/wrappedopenal.c +++ b/src/wrapped32/wrappedopenal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedpulsesimple.c b/src/wrapped32/wrappedpulsesimple.c index bea4f1b7a..88015c1b2 100644 --- a/src/wrapped32/wrappedpulsesimple.c +++ b/src/wrapped32/wrappedpulsesimple.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedsdl1.c b/src/wrapped32/wrappedsdl1.c index 92f6fad54..399a593fe 100644 --- a/src/wrapped32/wrappedsdl1.c +++ b/src/wrapped32/wrappedsdl1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedsdl2.c b/src/wrapped32/wrappedsdl2.c index 842934f6c..55369dd6c 100644 --- a/src/wrapped32/wrappedsdl2.c +++ b/src/wrapped32/wrappedsdl2.c @@ -3,7 +3,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedsdl2image.c b/src/wrapped32/wrappedsdl2image.c index 3f07cf1bf..a9e20e064 100644 --- a/src/wrapped32/wrappedsdl2image.c +++ b/src/wrapped32/wrappedsdl2image.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedselinux.c b/src/wrapped32/wrappedselinux.c index b7a8d0bab..f6ce6b5a9 100644 --- a/src/wrapped32/wrappedselinux.c +++ b/src/wrapped32/wrappedselinux.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedtcmallocminimal.c b/src/wrapped32/wrappedtcmallocminimal.c index 154cdfcab..627603d34 100644 --- a/src/wrapped32/wrappedtcmallocminimal.c +++ b/src/wrapped32/wrappedtcmallocminimal.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/src/wrapped32/wrappedudev0.c b/src/wrapped32/wrappedudev0.c index 365756218..39caea560 100644 --- a/src/wrapped32/wrappedudev0.c +++ b/src/wrapped32/wrappedudev0.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedudev1.c b/src/wrapped32/wrappedudev1.c index bd0d602a8..0ccc7f097 100644 --- a/src/wrapped32/wrappedudev1.c +++ b/src/wrapped32/wrappedudev1.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include diff --git a/src/wrapped32/wrappedxinerama.c b/src/wrapped32/wrappedxinerama.c index 534f55c23..61d340fd8 100644 --- a/src/wrapped32/wrappedxinerama.c +++ b/src/wrapped32/wrappedxinerama.c @@ -2,7 +2,6 @@ #include #include #include -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "wrappedlibs.h" diff --git a/system/box64.box64rc b/system/box64.box64rc index 0b6f3c15e..f5f66889f 100644 --- a/system/box64.box64rc +++ b/system/box64.box64rc @@ -378,7 +378,7 @@ BOX64_NOGTK=1 [steam] BOX64_EMULATED_LIBS=libudev.so.0 BOX64_DYNAREC_BIGBLOCK=3 -BOX64_DYNAREC_STRONGMEM=2 +#BOX64_DYNAREC_STRONGMEM=2 #seems useless now BOX64_NOGTK=1 # this is for the 64bits version of the client [steamwebhelper] @@ -391,7 +391,7 @@ BOX64_DYNAREC_SAFEFLAGS=0 BOX64_ARCH=la64 BOX64_EMULATED_LIBS=libudev.so.0 BOX64_DYNAREC_BIGBLOCK=3 -BOX64_DYNAREC_STRONGMEM=2 +#BOX64_DYNAREC_STRONGMEM=2 BOX64_STEAM_VULKAN=1 BOX64_NOGTK=1 @@ -410,7 +410,7 @@ BOX64_SHAEXT=0 BOX64_PCLMULQDQ=0 BOX64_EMULATED_LIBS=libudev.so.0 BOX64_DYNAREC_BIGBLOCK=3 -BOX64_DYNAREC_STRONGMEM=2 +#BOX64_DYNAREC_STRONGMEM=2 BOX64_STEAM_VULKAN=1 BOX64_NOGTK=1 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 79b32b07f..7d523cfd2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -82,6 +82,7 @@ box64_add_test(Boundary 33 DISABLED_ON_ANDROID) box64_add_test(mmx 34) box64_add_test(xsave_xrstor 35 DISABLED_ON_ANDROID) box64_add_test(mxcsr_rounding_interpreter 36 ENV "BOX64_DYNAREC=0;BOX64_AVX=2" DISABLED_ON_ANDROID) +box64_add_test(move_imm 37 ARGS2 quick DISABLED_ON_ANDROID) if(BOX32) box64_add_test(bootSyscall_32bits 01 32BIT) diff --git a/tests/ref37.txt b/tests/ref37.txt new file mode 100644 index 000000000..48d8cfd38 --- /dev/null +++ b/tests/ref37.txt @@ -0,0 +1,5 @@ +mov r64, imm64: 69154 values ok +mov r32, imm32: 83538 values ok +mov r64, imm32: 83538 values ok +mov qword [rdi+disp], imm32: 66154 values ok +move immediate: PASS diff --git a/tests/test17.c b/tests/test17.c index 9e5260fbf..19607d1f1 100644 --- a/tests/test17.c +++ b/tests/test17.c @@ -148,7 +148,7 @@ void print_64(v128 v) { #define print_128 print_64 void print_ps(v128 v) { for(int i=0; i<4; ++i) - if(isnanf(v.f32[i])) + if(isnan(v.f32[i])) printf("nan "); else printf("%g ", v.f32[i]); diff --git a/tests/test30.c b/tests/test30.c index e611306fd..21ec6c177 100644 --- a/tests/test30.c +++ b/tests/test30.c @@ -163,7 +163,7 @@ void print_64(v128 v) { #define print_128 print_64 void print_ps(v128 v) { for(int i=0; i<4; ++i) - if(isnanf(v.f32[i])) + if(isnan(v.f32[i])) printf("%cnan ", (v.u32[i]&0x80000000)?'-':'+'); else printf("%g ", v.f32[i]); diff --git a/tests/test37 b/tests/test37 new file mode 100755 index 000000000..1feae4e70 Binary files /dev/null and b/tests/test37 differ diff --git a/tests/test37.c b/tests/test37.c new file mode 100644 index 000000000..5689e2365 --- /dev/null +++ b/tests/test37.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: MIT +#include +#include +#include +#include +#include + +#define BLOCK_VALUES 2048 +#define N16 0x10000u +#define N24 0x1000000u +#define STEP24 31u +#define NRAND64 50000u +#define NRAND32 12500u +#define NPOW (64u * 9u) + +enum { + F_MOV64, + F_MOV32, + F_MOVSXD, + F_STORE32, + F_COUNT +}; + +static uint8_t* pool; +static size_t pool_used; +static size_t pool_size; +static uint64_t checked[F_COUNT]; +static uint64_t failures; + +static void* alloc_code(size_t bytes) +{ + void* p; + if (pool_used + bytes > pool_size) { + fprintf(stderr, "code pool exhausted\n"); + exit(1); + } + p = pool + pool_used; + pool_used += bytes; + return p; +} + +static size_t emit_mov64(uint8_t* p, uint64_t v, int32_t disp) +{ + p[0] = 0x48; + p[1] = 0xB8; + memcpy(p + 2, &v, 8); + p[10] = 0x48; + p[11] = 0x89; + p[12] = 0x87; + memcpy(p + 13, &disp, 4); + return 17; +} + +static size_t emit_mov32(uint8_t* p, uint32_t v, int32_t disp) +{ + p[0] = 0xB8; + memcpy(p + 1, &v, 4); + p[5] = 0x48; + p[6] = 0x89; + p[7] = 0x87; + memcpy(p + 8, &disp, 4); + return 12; +} + +static size_t emit_movsxd(uint8_t* p, int32_t v, int32_t disp) +{ + p[0] = 0x48; + p[1] = 0xC7; + p[2] = 0xC0; + memcpy(p + 3, &v, 4); + p[7] = 0x48; + p[8] = 0x89; + p[9] = 0x87; + memcpy(p + 10, &disp, 4); + return 14; +} + +static size_t emit_store32(uint8_t* p, int32_t v, int32_t disp) +{ + p[0] = 0x48; + p[1] = 0xC7; + p[2] = 0x87; + memcpy(p + 3, &disp, 4); + memcpy(p + 7, &v, 4); + return 11; +} + +static size_t emit_value(int form, uint8_t* p, uint64_t v, int32_t disp) +{ + switch (form) { + case F_MOV64: + return emit_mov64(p, v, disp); + case F_MOV32: + return emit_mov32(p, (uint32_t)v, disp); + case F_MOVSXD: + return emit_movsxd(p, (int32_t)v, disp); + default: + return emit_store32(p, (int32_t)v, disp); + } +} + +static uint64_t expected(int form, uint64_t v) +{ + switch (form) { + case F_MOV64: + return v; + case F_MOV32: + return (uint32_t)v; + default: + return (uint64_t)(int64_t)(int32_t)v; + } +} + +typedef void (*block_fn)(uint64_t*); + +static void run_values(int form, const uint64_t* values, size_t count) +{ + size_t nblocks = (count + BLOCK_VALUES - 1) / BLOCK_VALUES; + size_t i, b; + uint8_t* start; + uint8_t* p; + uint8_t** blocks; + + start = alloc_code(count * 17 + nblocks); + blocks = malloc(nblocks * sizeof(*blocks)); + if (!blocks) exit(1); + + p = start; + for (b = 0; b < nblocks; ++b) { + size_t base = b * BLOCK_VALUES; + size_t n = count - base; + if (n > BLOCK_VALUES) n = BLOCK_VALUES; + blocks[b] = p; + for (i = 0; i < n; ++i) + p += emit_value(form, p, values[base + i], (int32_t)(i * 8)); + *p++ = 0xC3; + } + __builtin___clear_cache((char*)start, (char*)p); + + for (b = 0; b < nblocks; ++b) { + size_t base = b * BLOCK_VALUES; + size_t n = count - base; + uint64_t out[BLOCK_VALUES]; + block_fn fn = (block_fn)blocks[b]; + if (n > BLOCK_VALUES) n = BLOCK_VALUES; + fn(out); + for (i = 0; i < n; ++i) { + uint64_t want = expected(form, values[base + i]); + checked[form]++; + if (out[i] != want) { + if (failures < 20) + printf("FAIL form=%d value=%016llx expected=%016llx got=%016llx\n", form, + (unsigned long long)values[base + i], (unsigned long long)want, + (unsigned long long)out[i]); + failures++; + } + } + } + + free(blocks); +} + +static uint64_t rng_state = 0x123456789abcdefULL; + +static uint64_t rng(void) +{ + rng_state ^= rng_state << 13; + rng_state ^= rng_state >> 7; + rng_state ^= rng_state << 17; + return rng_state; +} + +static const uint64_t special[] = { + 0, 1, 2, 3, 0x7F, 0x80, 0xFF, 0x100, 0x7FFF, 0x8000, 0xFFFF, 0x10000, + 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF, 0x100000000, + 0x7FFFFFFFFFFFFFFF, 0x8000000000000000, 0xFFFFFFFFFFFFFFFF, + 0xFFFF0000FFFF0000, 0x0000FFFF0000FFFF, 0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00, + 0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 0x3333333333333333, 0xCCCCCCCCCCCCCCCC, + 0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 0x0101010101010101, 0x8080808080808080, + 0x123456789ABCDEF0, 0xFEDCBA9876543210, 0xDEADBEEFCAFEBABE, + 0x00000000FFFFFFFF, 0xFFFFFFFF00000000, 0x0000000100000001, 0xFFFFFFFF00000001, + 0x7FFFFFFFFFFFFFFE, 0x8000000000000001, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFEFFFFFFFF +}; + +static void print_group(int form) +{ + static const char* name[F_COUNT] = { + "mov r64, imm64", + "mov r32, imm32", + "mov r64, imm32", + "mov qword [rdi+disp], imm32" + }; + printf("%s: %llu values ok\n", name[form], (unsigned long long)checked[form]); +} + +int main(int argc, char** argv) +{ + int quick = argc > 1 && !strcmp(argv[1], "quick"); + uint64_t* v16; + uint64_t* v24; + uint64_t* r64; + uint64_t* r32; + uint64_t* kpow; + uint64_t step24 = quick ? 0x400 : STEP24; + size_t nrand64 = quick ? 2000 : NRAND64; + size_t nrand32 = quick ? 1000 : NRAND32; + size_t n24 = (N24 - 1) / step24 + 1; + uint64_t i, k; + int d; + + pool_size = 64u << 20; + pool = mmap(NULL, pool_size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (pool == MAP_FAILED) { + perror("mmap"); + return 1; + } + + v16 = malloc(N16 * sizeof(uint64_t)); + v24 = malloc(n24 * sizeof(uint64_t)); + r64 = malloc(nrand64 * sizeof(uint64_t)); + r32 = malloc(nrand32 * sizeof(uint64_t)); + kpow = malloc(NPOW * sizeof(uint64_t)); + if (!v16 || !v24 || !r64 || !r32 || !kpow) { + perror("malloc"); + return 1; + } + + for (i = 0; i < N16; ++i) + v16[i] = i; + for (i = 0; i < n24; ++i) + v24[i] = i * step24; + for (i = 0; i < nrand64; ++i) + r64[i] = rng(); + for (i = 0; i < nrand32; ++i) + r32[i] = (uint32_t)rng(); + i = 0; + for (k = 0; k < 64; ++k) { + for (d = -0x1000; d <= 0x1000; d += 0x400) { + kpow[i] = (UINT64_C(1) << k) + (uint64_t)(int64_t)d; + ++i; + } + } + + run_values(F_MOV64, v16, N16); + run_values(F_MOV64, r64, nrand64); + run_values(F_MOV64, r32, nrand32); + run_values(F_MOV64, kpow, NPOW); + run_values(F_MOV64, special, sizeof(special) / sizeof(special[0])); + + run_values(F_MOV32, v16, N16); + run_values(F_MOV32, v24, n24); + run_values(F_MOV32, r32, nrand32); + run_values(F_MOV32, kpow, NPOW); + run_values(F_MOV32, special, sizeof(special) / sizeof(special[0])); + + run_values(F_MOVSXD, v16, N16); + run_values(F_MOVSXD, v24, n24); + run_values(F_MOVSXD, r32, nrand32); + run_values(F_MOVSXD, kpow, NPOW); + run_values(F_MOVSXD, special, sizeof(special) / sizeof(special[0])); + + run_values(F_STORE32, v16, N16); + run_values(F_STORE32, kpow, NPOW); + run_values(F_STORE32, special, sizeof(special) / sizeof(special[0])); + + for (d = 0; d < F_COUNT; ++d) + print_group(d); + printf("move immediate: %s\n", failures ? "FAILED" : "PASS"); + + free(v16); + free(v24); + free(r64); + free(r32); + free(kpow); + return failures ? 1 : 0; +} diff --git a/tests32/test17.c b/tests32/test17.c index 04968b6f4..f4c7d6e1c 100644 --- a/tests32/test17.c +++ b/tests32/test17.c @@ -148,7 +148,7 @@ void print_64(v128 v) { #define print_128 print_64 void print_ps(v128 v) { for(int i=0; i<4; ++i) - if(isnanf(v.f32[i])) + if(isnan(v.f32[i])) printf("nan "); else printf("%g ", v.f32[i]); diff --git a/wine/box64ec/CMakeLists.txt b/wine/box64ec/CMakeLists.txt index 148b525cc..cd7de0b4c 100644 --- a/wine/box64ec/CMakeLists.txt +++ b/wine/box64ec/CMakeLists.txt @@ -5,6 +5,7 @@ find_package(Python3 REQUIRED COMPONENTS Interpreter) set(BOX64_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../..") +string(REPLACE "," ";" DYNAREC_PASS "${DYNAREC_PASS_STR}") string(REPLACE "," ";" INTERPRETER "${INTERPRETER_STR}") if(NOT INTERPRETER) message(FATAL_ERROR "Build Box64EC from the parent project with -DARM64EC=ON") @@ -51,7 +52,28 @@ add_library(box64ec SHARED "${BOX64_ROOT}/external/musl/sqrt_data.c" "${BOX64_ROOT}/external/musl/sqrtf.c" ) -foreach(target box64ec box64ec_interpreter) +set(BOX64EC_TARGETS box64ec box64ec_interpreter) + +# The Dynarec emitters are only compiled for now, the DLL does not link them yet. +if(DYNAREC_PASS) + add_library(box64ec_dynarec_helpers OBJECT + "${BOX64_ROOT}/src/dynarec/arm64/arm64_immenc.c" + "${BOX64_ROOT}/src/dynarec/arm64/arm64_printer.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_arch.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_functions.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_jmpnext.c" + "${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_consts.c" + "${BOX64_ROOT}/src/dynarec/arm64/updateflags_arm64.c") + target_compile_definitions(box64ec_dynarec_helpers PRIVATE DYNAREC) + list(APPEND BOX64EC_TARGETS box64ec_dynarec_helpers) + foreach(STEP_VALUE RANGE 3) + add_library(box64ec_dynarec_pass${STEP_VALUE} OBJECT ${DYNAREC_PASS}) + target_compile_definitions(box64ec_dynarec_pass${STEP_VALUE} PRIVATE DYNAREC STEP=${STEP_VALUE}) + list(APPEND BOX64EC_TARGETS box64ec_dynarec_pass${STEP_VALUE}) + endforeach() +endif() + +foreach(target ${BOX64EC_TARGETS}) target_include_directories(${target} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" "${BOX64_ROOT}/src/include" diff --git a/wine/common/wrt.c b/wine/common/wrt.c index a302c98ce..cb03ff1c0 100644 --- a/wine/common/wrt.c +++ b/wine/common/wrt.c @@ -93,6 +93,7 @@ DWORD WINAPI GetEnvironmentVariableA(LPCSTR name, LPSTR value, DWORD size) else { ret = 0; if (len) RtlUnicodeToMultiByteN(value, size, &ret, valueW, len * sizeof(WCHAR)); + if (ret < size) value[ret] = 0; } RtlFreeUnicodeString(&nameU); diff --git a/wine/wow64/wowbox64.c b/wine/wow64/wowbox64.c index 7ee9fe474..b1c36728b 100644 --- a/wine/wow64/wowbox64.c +++ b/wine/wow64/wowbox64.c @@ -16,6 +16,7 @@ #include "env.h" #include "emu/x64emu_private.h" #include "emu/x87emu_private.h" +#include "emu/x64run_private.h" #include "x64trace.h" #include "box64context.h" #include "box64cpu.h" @@ -307,13 +308,6 @@ NTSTATUS WINAPI BTCpuProcessInit(void) return STATUS_SUCCESS; } -static uint8_t box64_is_addr_in_jit(void* addr) -{ - if (!addr) - return FALSE; - return !!FindDynablockFromNativeAddress(addr); -} - NTSTATUS WINAPI BTCpuResetToConsistentState(EXCEPTION_POINTERS* ptrs) { printf_log(LOG_DEBUG, "BTCpuResetToConsistentState(%p)\n", ptrs); @@ -335,9 +329,34 @@ NTSTATUS WINAPI BTCpuResetToConsistentState(EXCEPTION_POINTERS* ptrs) } } - if (!box64_is_addr_in_jit(ULongToPtr(ctx->Pc))) + dynablock_t* db = FindDynablockFromNativeAddress((void*)ctx->Pc); + if (!db) return STATUS_SUCCESS; + { + WOW64_CPURESERVED* cpu = NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED]; + WOW64_CONTEXT* wctx = (WOW64_CONTEXT*)(cpu + 1); + uintptr_t x64pc = getX64Address(db, ctx->Pc); + + for (int i = 0; i < 8; i++) // x10-x17 hold RAX-RDI + emu->regs[i].q[0] = (uint32_t)ctx->X[10 + i]; + emu->eflags.x64 = (uint32_t)ctx->X[26]; + CHECK_FLAGS(emu); + R_RIP = x64pc ? x64pc : (uint32_t)ctx->X[27]; + + wctx->Eax = R_EAX; + wctx->Ecx = R_ECX; + wctx->Edx = R_EDX; + wctx->Ebx = R_EBX; + wctx->Esp = R_ESP; + wctx->Ebp = R_EBP; + wctx->Esi = R_ESI; + wctx->Edi = R_EDI; + wctx->Eip = R_RIP; + wctx->EFlags = emu->eflags.x64; + box_to_fpu(wctx, emu); + } + /* Replace the host context with one captured before JIT entry so host code can unwind */ memcpy(ctx, NtCurrentTeb()->TlsSlots[WOW64_TLS_ENTRY_CONTEXT], sizeof(*ctx)); return STATUS_SUCCESS; diff --git a/wrapperhelper/example-libc.h b/wrapperhelper/example-libc.h index 4ead3e38a..d65d4acc4 100644 --- a/wrapperhelper/example-libc.h +++ b/wrapperhelper/example-libc.h @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#define _GNU_SOURCE 1 #define __USE_MISC 1 #define PORTMAP