mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-29 01:56:06 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 76bbb973c6 | |||
| ebb9a9c8f3 | |||
| 6802b5b8e5 | |||
| e26cb4e6f2 | |||
| 75bfed0a3a | |||
| dd352f8ce7 | |||
| d4764811b0 | |||
| f5687b4af0 | |||
| 6eea2adcea | |||
| 88c87629df | |||
| 2389032f39 | |||
| e8577c9ab5 | |||
| 1301af96af | |||
| 978770372b | |||
| 07a4292f87 | |||
| 7e6d28f54a | |||
| a8b99595d5 | |||
| d2d495d263 | |||
| 9d36a0973a | |||
| f80ecd6f75 | |||
| 057e09627f | |||
| cc570b89cb | |||
| 5afcfd0de5 | |||
| cc9e023a01 | |||
| a35d1f7183 | |||
| d2b5af5d8a | |||
| b8c987013c | |||
| 20e039331d | |||
| 04ca01f5ea | |||
| dc5bdfe5ca | |||
| cb6435a88d | |||
| 78a5155e2e | |||
| 0860070b26 | |||
| 8cb83e22df | |||
| f3a5934ae4 | |||
| 9e5271eb0d | |||
| 375b5ddaf7 | |||
| ecffaf558a | |||
| da5accd1c2 | |||
| 15701abe1d | |||
| a86511a282 | |||
| 5812e6a063 | |||
| a7fd1b79c2 | |||
| 3299ab33b8 | |||
| e8276bedaf |
@@ -19,6 +19,7 @@ log.txt
|
||||
# Generated source files
|
||||
src/common/scm_rev.cpp
|
||||
dist/english_plurals/generated_en.ts
|
||||
*-toolchain.cmake
|
||||
|
||||
# Project/editor files
|
||||
*.swp
|
||||
|
||||
+4
-6
@@ -81,9 +81,6 @@ cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSV
|
||||
option(ENABLE_DEBUG_TOOLS "Enable debugging tools (maxwell disassembler, SPIRV translator, etc)" OFF)
|
||||
option(ENABLE_WERROR "Enable -Werror diagnostics" ON)
|
||||
|
||||
# Lossless Scaling frame generation. Only Android.
|
||||
cmake_dependent_option(ENABLE_LSFG "Enable Lossless Scaling frame generation" ON "ANDROID" OFF)
|
||||
|
||||
# non-linux bundled qt are static
|
||||
if (YUZU_USE_BUNDLED_QT AND (APPLE OR NOT UNIX))
|
||||
set(YUZU_STATIC_BUILD ON)
|
||||
@@ -172,6 +169,8 @@ if (CXX_CLANG_CL)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat-pedantic>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c98-compat>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-extensions>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc>)
|
||||
# REQUIRED CPU features IN Windows-amd64
|
||||
if (ARCHITECTURE_x86_64)
|
||||
@@ -340,12 +339,11 @@ if (CXX_GCC OR CXX_CLANG)
|
||||
endif()
|
||||
elseif(ARCHITECTURE_arm64)
|
||||
# See https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
|
||||
set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, optimized, armv9, native")
|
||||
set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, armv9, native")
|
||||
set(mtune generic)
|
||||
|
||||
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
|
||||
set(march armv8-a)
|
||||
elseif (${YUZU_BUILD_PRESET} STREQUAL "optimized")
|
||||
set(march armv8.2-a+lse+rcpc)
|
||||
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv9")
|
||||
set(march armv9-a)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set(CROSS_TARGET "powerpc64le" CACHE STRING "Cross-compilation target (aarch64, powerpc64le, riscv64, etc)")
|
||||
|
||||
set(CMAKE_SYSROOT /usr/${CROSS_TARGET}-unknown-linux-gnu)
|
||||
|
||||
set(CMAKE_C_COMPILER ${CROSS_TARGET}-unknown-linux-gnu-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${CROSS_TARGET}-unknown-linux-gnu-g++)
|
||||
|
||||
# search programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
|
||||
# search headers and libraries in the target environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH /usr/${CROSS_TARGET}-unknown-linux-gnu)
|
||||
@@ -15,9 +15,8 @@
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
<h4 align="center"><b>Eden</b> is a free and open-source (FOSS) Switch 1 emulator started by developer Camille LaVey.
|
||||
<br>
|
||||
Written in C++, with builds for Windows, Linux, macOS, Android, FreeBSD and more.
|
||||
<h4 align="center"><b>Eden</b> is a free and opensource (FOSS) Switch 1 emulator, derived from Yuzu and Sudachi - started by developer Camille LaVey.
|
||||
It's written in C++ with portability in mind, with builds for Windows, Linux, macOS, Android, FreeBSD and more.
|
||||
</h4>
|
||||
|
||||
<p align="center">
|
||||
@@ -74,17 +73,3 @@ Save us some bandwidth! We have [mirrors available](./docs/user/ThirdParty.md#mi
|
||||
## License
|
||||
|
||||
Eden is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt) file.
|
||||
|
||||
## Special thanks
|
||||
|
||||
Super special thanks to Cloudflare for preventing the git server from blowing up.
|
||||
|
||||
- Yuzu
|
||||
- Ryujinx
|
||||
- Sudachi
|
||||
- Citron
|
||||
- Torzu
|
||||
- Suyu
|
||||
- Ryubing
|
||||
|
||||
And everyone who continues or had contributed to the project! <3
|
||||
|
||||
Vendored
+4
-5
@@ -11,12 +11,12 @@ SPDX-License-Identifier: CC0-1.0
|
||||
-->
|
||||
|
||||
<component type="desktop-application">
|
||||
<id>dev.eden_emu.eden</id>
|
||||
<id>org.eden_emu.eden</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<name>eden</name>
|
||||
<summary>Nintendo Switch emulator</summary>
|
||||
<description>
|
||||
<p>Eden is a free and open-source (FOSS) Switch 1 emulator started by developer Camille LaVey. Written in C++, with builds for Windows, Linux, macOS, Android, FreeBSD and more.</p>
|
||||
<p>Multiplatform FOSS Switch 1 emulator written in C++, derived from Yuzu and Sudachi</p>
|
||||
</description>
|
||||
<categories>
|
||||
<category>Game</category>
|
||||
@@ -32,10 +32,10 @@ SPDX-License-Identifier: CC0-1.0
|
||||
<url type="help">https://eden-emu.dev/docs</url>
|
||||
<url type="donation">https://eden-emu.dev/donations</url>
|
||||
<url type="translate">https://explore.transifex.com/edenemu/eden-emulator</url>
|
||||
<url type="contact">https://discord.gg/HstXbPch7X</url>
|
||||
<url type="contact">https://discord.gg/edenemu</url>
|
||||
<url type="vcs-browser">https://git.eden-emu.dev</url>
|
||||
<url type="contribute">https://git.eden-emu.dev/eden-emu/eden</url>
|
||||
<launchable type="desktop-id">dev.eden_emu.eden.desktop</launchable>
|
||||
<launchable type="desktop-id">org.eden_emu.eden.desktop</launchable>
|
||||
<provides>
|
||||
<binary>yuzu</binary>
|
||||
<binary>yuzu-cmd</binary>
|
||||
@@ -44,7 +44,6 @@ SPDX-License-Identifier: CC0-1.0
|
||||
<control>pointing</control>
|
||||
<control>keyboard</control>
|
||||
<control>gamepad</control>
|
||||
<internet>offline-only</internet>
|
||||
</supports>
|
||||
<requires>
|
||||
<memory>8192</memory>
|
||||
|
||||
Vendored
+4
-4
@@ -14,7 +14,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<mime-type type="application/x-nx-nro">
|
||||
<comment>Nintendo Switch homebrew executable</comment>
|
||||
<acronym>NRO</acronym>
|
||||
<icon name="dev.eden_emu.eden"/>
|
||||
<icon name="org.eden_emu.eden"/>
|
||||
<glob pattern="*.nro"/>
|
||||
<magic><match value="NRO" type="string" offset="16"/></magic>
|
||||
</mime-type>
|
||||
@@ -22,7 +22,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<mime-type type="application/x-nx-nso">
|
||||
<comment>Nintendo Switch homebrew executable</comment>
|
||||
<acronym>NSO</acronym>
|
||||
<icon name="dev.eden_emu.eden"/>
|
||||
<icon name="org.eden_emu.eden"/>
|
||||
<glob pattern="*.nso"/>
|
||||
<magic><match value="NSO" type="string" offset="0"/></magic>
|
||||
</mime-type>
|
||||
@@ -30,7 +30,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<mime-type type="application/x-nx-nsp">
|
||||
<comment>Nintendo Switch Package</comment>
|
||||
<acronym>NSP</acronym>
|
||||
<icon name="dev.eden_emu.eden"/>
|
||||
<icon name="org.eden_emu.eden"/>
|
||||
<glob pattern="*.nsp"/>
|
||||
<magic><match value="PFS" type="string" offset="0"/></magic>
|
||||
</mime-type>
|
||||
@@ -38,7 +38,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<mime-type type="application/x-nx-xci">
|
||||
<comment>Nintendo Switch Card Image</comment>
|
||||
<acronym>XCI</acronym>
|
||||
<icon name="dev.eden_emu.eden"/>
|
||||
<icon name="org.eden_emu.eden"/>
|
||||
<glob pattern="*.xci"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
|
||||
Vendored
+1
-3
@@ -2,7 +2,6 @@
|
||||
|
||||
Qt has "Translation Rules for Plurals", small example
|
||||
|
||||
```cpp
|
||||
// Take a source line like
|
||||
tr("Building: %n shader(s)", "", i)
|
||||
|
||||
@@ -10,9 +9,8 @@ Qt has "Translation Rules for Plurals", small example
|
||||
Building: 1 shader
|
||||
// i = 2:
|
||||
Building: 2 shaders
|
||||
```
|
||||
|
||||
For Yuzu the source language used is English, for all other languages handling of plurals is handled by Qt and the translation collaboration site. Handling plurals in the source language (English) requires special consideration.
|
||||
For yuzu the source language used is English, for all other languages handling of plurals is handled by Qt and the translation collaboration site. Handling plurals in the source language (English) requires special consideration.
|
||||
|
||||
With CMake flag GENERATE_QT_TRANSLATION a generated_en.ts file is created from the source. It ignored by git (`.gitignore` in the project root). It is placed in this directory so that the relative refrences with the source code is correct.
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Translating
|
||||
|
||||
This directory stores translation patches (TS files) for Yuzu Qt frontend. This directory is linked with the [Eden project on Transifex](https://app.transifex.com/edenemu/eden-emulator), so you can update the translation by executing `tx pull -t -a` in the root of this repository. If you want to contribute to the translation, please go the Transifex link and submit your translation there.
|
||||
This directory stores translation patches (TS files) for yuzu Qt frontend. This directory is linked with the [Eden project on transifex](https://app.transifex.com/edenemu/eden-emulator), so you can update the translation by executing `tx pull -t -a` in the root of this repository. If you want to contribute to the translation, please go the transifex link and submit your translation there.
|
||||
|
||||
When creating/improving translations, please keep in mind:
|
||||
|
||||
|
||||
Vendored
+575
-584
File diff suppressed because it is too large
Load Diff
Vendored
+572
-581
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+576
-583
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+576
-583
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+575
-583
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+573
-581
File diff suppressed because it is too large
Load Diff
Vendored
+576
-583
File diff suppressed because it is too large
Load Diff
Vendored
+576
-585
File diff suppressed because it is too large
Load Diff
Vendored
+635
-643
File diff suppressed because it is too large
Load Diff
Vendored
+573
-582
File diff suppressed because it is too large
Load Diff
Vendored
+574
-581
File diff suppressed because it is too large
Load Diff
Vendored
+576
-583
File diff suppressed because it is too large
Load Diff
Vendored
+576
-583
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+597
-613
File diff suppressed because it is too large
Load Diff
Vendored
+576
-583
File diff suppressed because it is too large
Load Diff
Vendored
+575
-583
File diff suppressed because it is too large
Load Diff
Vendored
+576
-583
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+571
-580
File diff suppressed because it is too large
Load Diff
Vendored
+585
-600
File diff suppressed because it is too large
Load Diff
Vendored
+573
-581
File diff suppressed because it is too large
Load Diff
+5
-11
@@ -5,12 +5,6 @@
|
||||
|
||||
This is a full-fledged guide to build Eden on all supported platforms.
|
||||
|
||||
TL;DR
|
||||
```sh
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild -GNinja
|
||||
cmake --build build -t yuzu --parallel
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
First, you must [install some dependencies](Deps.md).
|
||||
@@ -131,13 +125,13 @@ cmake -S . -B build -G "<GENERATOR>" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COM
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/42481638/216899164-6cee8482-3d59-428f-b1bc-e6dc793c9b20.png" width="500">
|
||||
|
||||
- Click OK; now CLion will build a directory and index your code to allow for IntelliSense. Please be patient.
|
||||
- Once this process has been completed (No loading bar bottom right), you can now build Eden
|
||||
- In the top right, click on the drop-down menu, select all configurations, then select Eden
|
||||
- Click OK; now Clion will build a directory and index your code to allow for IntelliSense. Please be patient.
|
||||
- Once this process has been completed (No loading bar bottom right), you can now build eden
|
||||
- In the top right, click on the drop-down menu, select all configurations, then select eden
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/42481638/216899226-975048e9-bc6d-4ec1-bc2d-bd8a1e15ed04.png" height="500" >
|
||||
|
||||
- Now run by clicking the play button or pressing Shift+F10, and Eden will auto-launch once built.
|
||||
- Now run by clicking the play button or pressing Shift+F10, and eden will auto-launch once built.
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/42481638/216899275-d514ec6a-e563-470e-81e2-3e04f0429b68.png" width="500">
|
||||
</details>
|
||||
@@ -159,7 +153,7 @@ If your initial configure failed:
|
||||
- *Carefully* re-read the [dependencies guide](Deps.md)
|
||||
- Clear the CPM cache (`.cache/cpm`) and CMake cache (`<build directory>/CMakeCache.txt`)
|
||||
- Evaluate the error and find any related settings
|
||||
- See the [CPM docs](CPMUtil.md) to see if you may need to forcefully bundle any packages
|
||||
- See the [CPM docs](CPM.md) to see if you may need to forcefully bundle any packages
|
||||
|
||||
Otherwise, feel free to ask for help in Stoat or Discord.
|
||||
|
||||
|
||||
+22
-4
@@ -12,6 +12,10 @@
|
||||
- [NetBSD](#netbsd)
|
||||
- [MSYS2](#msys2)
|
||||
- [RedoxOS](#redoxos)
|
||||
- [Windows](#windows)
|
||||
- [Windows 7, Windows 8 and Windows 8.1](#windows-7-windows-8-and-windows-81)
|
||||
- [Windows Vista and below](#windows-vista-and-below)
|
||||
- [Windows on ARM](#windows-on-arm)
|
||||
<!-- /TOC -->
|
||||
|
||||
## Arch Linux
|
||||
@@ -67,7 +71,7 @@ export LIBGL_ALWAYS_SOFTWARE=1
|
||||
|
||||
Install `developer/gcc14` on OmniOS using pkgsrc.
|
||||
|
||||
Since so many dependencies are missing on `OmniOS`, you may wish to use `-DCPMUTIL_FORCE_BUNDLED=ON` and `-DYUZU_USE_BUNDLED_OPENSSL=OFF`.
|
||||
Since so many dependencies are missing on `OmniOS`, you may wish to use `-DCPMUTIL_FORCE_BUNDLED=ON`
|
||||
|
||||
For OmniOS you are required to build glslang yourself:
|
||||
```sh
|
||||
@@ -86,9 +90,7 @@ Using `--parallel` on CMake incorrectly passes `dmake ... -jn` instead of `dmake
|
||||
|
||||
You may also need to install `gmake` in order to properly build FFmpeg, this is provided by the `build-essential` package.
|
||||
|
||||
If it wasn't obvious already, you require a X11 server to properly run the emulator within OmniOS, [this guide](https://web.archive.org/web/20260424200928/https://geekblood.wordpress.com/2017/10/26/installing-x11-and-a-desktop-environment-on-omnios/) is a great starting point for that, the links to pkgsrc are outdated so follow [this exemplar](https://pkgsrc.smartos.org/install-on-illumos/) as well.
|
||||
|
||||
For Solaris based OSes, `${CMAKE_SYSTEM_NAME}` isn't properly set on CMake (it's set to i686 on AMD64), you may find issues when building OpenSSL from `openssl-cmake`.
|
||||
If it wasn't obvious already, you require a X11 server to properly run the emulator within OmniOS, [this guide](https://web.archive.org/web/20260424200928/https://geekblood.wordpress.com/2017/10/26/installing-x11-and-a-desktop-environment-on-omnios/) is a great starting point for that, the links to pkgsrc are outdated so follow [this exemplar](https://pkgsrc.smartos.org/install-on-illumos/) as well:
|
||||
|
||||
## HaikuOS
|
||||
|
||||
@@ -242,3 +244,19 @@ find ./*/ -name "*.dll" | while read -r dll; do deps "$dll"; done
|
||||
The package install may randomly hang at times, in which case it has to be restarted. ALWAYS do a `sudo pkg update` or the chances of it hanging will be close to 90%. If "multiple" installs fail at once, try installing 1 by 1 the packages.
|
||||
|
||||
When CMake invokes certain file syscalls - it may sometimes cause crashes or corruptions on the (kernel?) address space - so reboot the system if there is a "hang" in CMake.
|
||||
|
||||
## Windows
|
||||
|
||||
### Windows 7, Windows 8 and Windows 8.1
|
||||
|
||||
DirectX 12 is not available - simply copy and paste a random DLL and name it `d3d12.dll`.
|
||||
|
||||
Install [Qt6 compatibility libraries](github.com/ANightly/qt6windows7) specifically Qt 6.9.5.
|
||||
|
||||
### Windows Vista and below
|
||||
|
||||
No support for Windows Vista (or below) is present at the moment. Check back later.
|
||||
|
||||
### Windows on ARM
|
||||
|
||||
If you're using Snapdragon X or 8CX, use the [the Vulkan translation layer](https://apps.microsoft.com/detail/9nqpsl29bfff?hl=en-us&gl=USE) only if the stock drivers do not work. And of course always keep your system up-to-date.
|
||||
|
||||
+137
-1
@@ -2,7 +2,122 @@
|
||||
|
||||
General guide for cross compiling.
|
||||
|
||||
## Debian ARM64
|
||||
## Gentoo
|
||||
|
||||
Gentoo's cross-compilation setup is relatively easy, provided you're already familiar with portage.
|
||||
|
||||
### Crossdev
|
||||
|
||||
First, emerge crossdev via `sudo emerge -a sys-devel/crossdev`.
|
||||
|
||||
Now, set up the environment depending on the target architecture; e.g.
|
||||
|
||||
```sh
|
||||
sudo crossdev powerpc64le
|
||||
sudo crossdev aarch64
|
||||
```
|
||||
|
||||
### QEMU
|
||||
|
||||
Installing a qemu user setup is recommended for testing. To do so, you will need the relevant USE flags:
|
||||
|
||||
```sh
|
||||
app-emulation/qemu static-user qemu_user_targets_ppc64le qemu_user_targets_aarch64
|
||||
```
|
||||
|
||||
Note that to use cross-emerged libraries, you will need to tell qemu where the sysroot is. You can do this with an alias:
|
||||
|
||||
```sh
|
||||
alias qemu-ppc64le="qemu-ppc64le -L /usr/powerpc64le-unknown-linux-gnu"
|
||||
alias qemu-aarch64="qemu-aarch64 -L /usr/aarch64-unknown-linux-gnu"
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
Some packages have broken USE flags on other architectures; you'll also need to set up python targets. In `/usr/<target>-unknown-linux-gnu/etc/portage/package.use`:
|
||||
|
||||
```sh
|
||||
>=net-misc/curl-8.16.0-r1 ssl
|
||||
|
||||
*/* PYTHON_TARGETS: python3_13 PYTHON_SINGLE_TARGET: python3_13
|
||||
*/* pam
|
||||
|
||||
sys-apps/util-linux pam su
|
||||
app-shells/bash -readline
|
||||
>=dev-libs/libpcre2-10.47 unicode
|
||||
>=x11-libs/libxkbcommon-1.12.3 X
|
||||
>=sys-libs/zlib-1.3.1-r1 minizip
|
||||
>=app-alternatives/gpg-1-r3 ssl
|
||||
>=app-crypt/gnupg-2.5.13-r2 ssl
|
||||
|
||||
dev-libs/* -introspection
|
||||
media-libs/harfbuzz -introspection
|
||||
dev-libs/quazip -qt5 qt6
|
||||
```
|
||||
|
||||
Dependencies should be about the same [as normal Gentoo](./Deps.md), but removing gamemode and renderdoc is recommended. Keep in mind that when emerging, you want to use `emerge-<target>-unknown-linux-gnu`, e.g. `emerge-powerpc64le-unknown-linux-gnu`.
|
||||
|
||||
Enable GURU in the cross environment (as root):
|
||||
|
||||
```sh
|
||||
mkdir -p /usr/powerpc64le-unknown-linux-gnu/etc/portage/repos.conf
|
||||
cat << EOF > /usr/powerpc64le-unknown-linux-gnu/etc/portage/repos.conf/guru.conf
|
||||
[guru]
|
||||
location = /var/db/repos/guru
|
||||
auto-sync = no
|
||||
priority = 1
|
||||
EOF
|
||||
```
|
||||
|
||||
Now emerge your dependencies:
|
||||
|
||||
```sh
|
||||
sudo emerge-powerpc64le-unknown-linux-gnu -aU app-arch/lz4 app-arch/zstd app-arch/unzip \
|
||||
dev-libs/libfmt dev-libs/libusb dev-libs/mcl dev-libs/sirit dev-libs/oaknut \
|
||||
dev-libs/unordered_dense dev-libs/boost dev-libs/openssl dev-libs/discord-rpc \
|
||||
dev-util/spirv-tools dev-util/spirv-headers dev-util/vulkan-headers \
|
||||
dev-util/vulkan-utility-libraries dev-util/glslang \
|
||||
media-libs/libva media-libs/opus media-video/ffmpeg \
|
||||
media-libs/VulkanMemoryAllocator media-libs/libsdl2 media-libs/cubeb \
|
||||
net-libs/enet net-libs/mbedtls \
|
||||
sys-libs/zlib \
|
||||
dev-cpp/nlohmann_json dev-cpp/simpleini dev-cpp/cpp-httplib dev-cpp/cpp-jwt dev-cpp/catch \
|
||||
net-wireless/wireless-tools \
|
||||
dev-qt/qtbase:6 dev-libs/quazip \
|
||||
virtual/pkgconfig
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
A toolchain is provided in `CMakeModules/GentooCross.cmake`. To use it:
|
||||
|
||||
```sh
|
||||
cmake -S . -B build/ppc64 -DCMAKE_TOOLCHAIN_FILE=CMakeModules/GentooCross.cmake -G Ninja -DCROSS_TARGET=powerpc64le -DENABLE_OPENGL=OFF
|
||||
```
|
||||
|
||||
Now build as normal:
|
||||
|
||||
```sh
|
||||
cmake --build build/ppc64 -j$(nproc)
|
||||
```
|
||||
|
||||
### Alternatively
|
||||
|
||||
Only emerge the absolute necessities:
|
||||
|
||||
```sh
|
||||
sudo emerge-powerpc64le-unknown-linux-gnu -aU media-video/ffmpeg media-libs/libsdl2 dev-qt/qtbase:6
|
||||
```
|
||||
|
||||
Then set `YUZU_USE_CPM=ON`:
|
||||
|
||||
```sh
|
||||
cmake -S . -B build/ppc64 -DCMAKE_TOOLCHAIN_FILE=CMakeModules/GentooCross.cmake -G Ninja -DCROSS_TARGET=powerpc64le -DENABLE_OPENGL=OFF -DYUZU_USE_CPM=ON
|
||||
```
|
||||
|
||||
## ARM64
|
||||
|
||||
### Debian ARM64
|
||||
|
||||
A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main.
|
||||
|
||||
@@ -88,3 +203,24 @@ And finally, run the compiled executable with QEMU!
|
||||
```sh
|
||||
qemu-aarch64 build/aarch64/bin/eden
|
||||
```
|
||||
|
||||
## PowerPC
|
||||
|
||||
This is a guide for FreeBSD users mainly.
|
||||
|
||||
Now you got a PowerPC sysroot - quickly decompress it somewhere, say `/home/user/opt/powerpc64le`. Create a toolchain file, for example `powerpc64le-toolchain.cmake`; always [consult the manual](https://man.freebsd.org/cgi/man.cgi?query=cmake-toolchains&sektion=7&manpath=FreeBSD+13.2-RELEASE+and+Ports).
|
||||
|
||||
There is a script to automatically do all of this under `./tools/setup-cross-sysroot.sh`.
|
||||
|
||||
Remember to add `-mabi=elfv1` to `CFLAGS`/`CXXFLAGS` otherwise the program will crash.
|
||||
|
||||
Specify:
|
||||
|
||||
- `YUZU_USE_CPM`: Set this to `ON` so packages can be found and built if your sysroot doesn't have them.
|
||||
- `YUZU_USE_EXTERNAL_FFMPEG`: Set this to `ON` as well.
|
||||
|
||||
Then run using a program such as QEMU to emulate userland syscalls:
|
||||
|
||||
```sh
|
||||
cmake --build build-ppc64-pc-freebsd -t dynarmic_tests -- -j8 && qemu-ppc64-static -L $HOME/opt/ppc64-freebsd/sysroot ./build-ppc64-pc-freebsd/bin/dynarmic_tests
|
||||
```
|
||||
|
||||
+5
-54
@@ -6,7 +6,7 @@ When reporting issues or finding bugs, we often need backtraces, debug logs, or
|
||||
|
||||
### Graphics Debugging
|
||||
|
||||
If your bug is related to a graphical issue -- e.g. mismatched colors, vertex explosions, flickering, etc. -- then you are required to include graphical debugging logs in your issue reports.
|
||||
If your bug is related to a graphical issue--e.g. mismatched colors, vertex explosions, flickering, etc.--then you are required to include graphical debugging logs in your issue reports.
|
||||
|
||||
Graphics Debugging is found in General -> Debug on desktop, and Advanced Settings -> Debug on Android. Android users are all set; however, desktop users may need to install the Vulkan Validation Layers:
|
||||
|
||||
@@ -17,7 +17,7 @@ Once Graphics Debugging is enabled, run the problematic game again and continue.
|
||||
|
||||
### Debug Logs
|
||||
|
||||
Debug logs can be found in `General -> Debug -> Open Log Location` on desktop, and `Share Debug Logs` on Android. This MUST be included in all bug reports, except for certain UI bugs -- but we still highly recommend them even for UI bugs.
|
||||
Debug logs can be found in General -> Debug -> Open Log Location on desktop, and Share Debug Logs on Android. This MUST be included in all bug reports, except for certain UI bugs--but we still highly recommend them even for UI bugs.
|
||||
|
||||
## Debugging (host code)
|
||||
|
||||
@@ -38,7 +38,7 @@ You must have GDB installed for aarch64 to debug the target. Install it through
|
||||
- `sudo emerge --ask crossdev`
|
||||
- `sudo crossdev -t aarch64-unknown-linux-gnu --ex-gdb`
|
||||
|
||||
Run `./build/bin/eden-cli -c <path to your config file (see logs where you run Eden normally to see where it is)> -d -g <path to game>`, or `Enable GDB Stub` at General > Debug, then hook up an aarch64-gdb:
|
||||
Run `./build/bin/eden-cli -c <path to your config file (see logs where you run eden normally to see where it is)> -d -g <path to game>`, or `Enable GDB Stub` at General > Debug, then hook up an aarch64-gdb:
|
||||
|
||||
- `target remote localhost:6543`
|
||||
|
||||
@@ -69,55 +69,6 @@ Expressions can be `variable_names` or `1234` (numbers) or `*var` (dereference o
|
||||
|
||||
For more information type `info gdb` and read [the man page](https://man7.org/linux/man-pages/man1/gdb.1.html).
|
||||
|
||||
# RenderDoc
|
||||
# RenderDoc (Graphic Debugging Tool)
|
||||
|
||||
RenderDoc is a free, cross platform, multi-graphics API debugger. It is an invaluable tool for diagnosing issues with graphics applications, and includes support for Vulkan. Get it from [renderdoc.org](https://renderdoc.org).
|
||||
|
||||
RenderDoc can capture Eden's Vulkan output when its Vulkan layer is loaded before Eden creates the Vulkan device. Before using RenderDoc to diagnose issues, it's always good to make sure there are no validation errors. Any errors means the behavior of the application is undefined. That said, RenderDoc can help debug validation errors if you do have them.
|
||||
|
||||
## Usage on Windows
|
||||
|
||||
You can either use RenderDoc UI to launch Eden, or you can make Eden attach it internally:
|
||||
|
||||
On Windows PowerShell:
|
||||
```powershell
|
||||
$env:ENABLE_VULKAN_RENDERDOC_CAPTURE='1'
|
||||
.\eden.exe
|
||||
```
|
||||
When RenderDoc is attached, Eden logs the default Windows capture folder:
|
||||
```text
|
||||
%LOCALAPPDATA%\Temp\RenderDoc
|
||||
```
|
||||
|
||||
Press RenderDoc's capture hotkey, usually `F12`, to capture a frame. To stop using RenderDoc, close Eden and launch it again without `ENABLE_VULKAN_RENDERDOC_CAPTURE`.
|
||||
|
||||
## Eden Hotkey
|
||||
|
||||
Eden also has a separate `Toggle Renderdoc Capture` hotkey behind the debug setting `renderdoc_hotkey`.
|
||||
That hotkey does not load or unload RenderDoc. It only toggles Eden's own manual capture through RenderDoc's API:
|
||||
|
||||
- First press: Starts a capture
|
||||
- Second press: Ends that capture
|
||||
|
||||
## Simple checklist for debugging black screens using Renderdoc
|
||||
|
||||
When debugging a black screen, there are many ways the application could have setup Vulkan wrong.
|
||||
Here is a short checklist of items to look at to make sure are appropriate:
|
||||
|
||||
- Draw call counts are correct (aka not zero, or if rendering many triangles, not 3)
|
||||
- Vertex buffers are bound
|
||||
- vertex attributes are correct - Make sure the size & offset of each attribute matches what should it should be
|
||||
- Any bound push constants and descriptors have the right data - including:
|
||||
- Matrices have correct values - double check the model, view, & projection matrices are uploaded correctly
|
||||
- Pipeline state is correct
|
||||
- viewport range is correct - x,y are 0,0; width & height are screen dimensions, minDepth is 0, maxDepth is 1, NDCDepthRange is 0,1
|
||||
- Fill mode matches expected - usually solid
|
||||
- Culling mode makes sense - commonly back or none
|
||||
- The winding direction is correct - typically CCW (counter clockwise)
|
||||
- Scissor region is correct - usually same as viewport's x,y,width, &height
|
||||
- Blend state is correct
|
||||
- Depth state is correct - typically enabled with Function set to Less than or Equal
|
||||
- Swapchain images are bound when rendering to the swapchain
|
||||
- Image being rendered to is the same as the one being presented when rendering to the swapchain
|
||||
|
||||
Alternatively, a [RenderDoc Extension](https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw) ([Archive](https://web.archive.org/web/20250000000000*/https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw)) exists which automates doing a lot of these manual steps.
|
||||
Guidelines for graphical debugging using RenderDoc: **[RenderDoc usage](./RenderDoc.md)**
|
||||
+2
-5
@@ -260,10 +260,7 @@ brew install molten-vk
|
||||
<details>
|
||||
<summary>FreeBSD</summary>
|
||||
|
||||
As root run:
|
||||
```sh
|
||||
pkg install devel/cmake devel/sdl3 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base x11-toolkits/qt6-charts devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/unordered-dense vulkan-headers quazip-qt6
|
||||
```
|
||||
As root run: `pkg install devel/cmake sdl3 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/qt6-charts devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/unordered-dense vulkan-headers quazip-qt6`
|
||||
|
||||
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
|
||||
|
||||
@@ -276,7 +273,7 @@ If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
|
||||
For NetBSD +10.1:
|
||||
|
||||
```sh
|
||||
pkgin install git cmake boost fmtlib SDL3 catch2 libjwt spirv-headers spirv-tools ffmpeg7 libva nlohmann-json jq libopus qt6-qtbase qt6-qtcharts qt6-qtmultimedia qt6-qttools cpp-httplib lz4 vulkan-headers nasm autoconf enet pkg-config libusb1 libcxx frozen
|
||||
pkgin install git cmake boost fmtlib SDL3 catch2 libjwt spirv-headers spirv-tools ffmpeg7 libva nlohmann-json jq libopus qt6 cpp-httplib lz4 vulkan-headers nasm autoconf enet pkg-config libusb1 libcxx frozen
|
||||
```
|
||||
|
||||
[Caveats](./Caveats.md#netbsd).
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# Design Overview
|
||||
|
||||
Modern game consoles require heavy power to be emulated appropriately. This is why the emulator uses an approach known as HLE (High-Level-Emulation), in a nutshell: Instead of accurately emulating every subsystem that forms part of a component, emulate the resulting visible I/O interface instead.
|
||||
|
||||
For example, take a disk write, instead of emulating a proper SD card we instead use the C++ standard library for I/O. Additionally we use the abstractions provided by the `fs` service to "lie" to programs about certain SD card properties. Notably this includes making up sizes for the fake SD card, giving "realistic" values or expected outputs for a given card, and so on. And instead of writing to an actual SD card, the emulator simply writes to a file.
|
||||
|
||||
This also means grand part of the emulator consists of just re-implementing firmware but using HLE primitives; for example audio doesn't go to an emulated audio device, but rather gets processed on the fly by a dedicated service and then passed to SDL3/cubeb/etc.
|
||||
|
||||
As such, many of the systems implemented are not 100% accurate to the original software, but they're "good enough" to pass as being so. While we do strive to maintain high compatibility (especially with homebrew), there are realistic limitations to these approaches.
|
||||
|
||||
No formal fuzzing or formal verification has been done on the emulator as a whole, this means there may be hundreds of bugs hiding in each subsystem. As such, output may also not correctly match due to those aforementioned issues.
|
||||
|
||||
## src/android/
|
||||
|
||||
Entire Android frontend, written mostly in Kotlin and generally having asinine hacks (thanks Android) due to the particularly horrific (and particular way) to do things.
|
||||
|
||||
## src/audio_core/
|
||||
|
||||
Handles everything related to audio, this is where most of the filtering and processing occurs (CPU intensive task!).
|
||||
|
||||
## src/common/
|
||||
|
||||
The [common](../src/common) folder contains just your basic polyfills for whatever missing functionality. We heavily encourage new PRs to make use of one of the dependencies, or the standard C++ library. Minimizing the amount of things we reinvent the wheel for is always a good thing.
|
||||
|
||||
## src/core/
|
||||
|
||||
The [core folder](../src/core) is the main heart of the emulator, while we don't officially support having other frontends out of the box (RetroArch, for example); any prospective developer can reuse this library (compiled as one by CMake) to stitch up their own RetroArch core, for example.
|
||||
|
||||
## src/dynarmic/
|
||||
|
||||
See [Dynarmic](./dynarmic).
|
||||
|
||||
## src/hid_core/
|
||||
|
||||
Input, joysticks, controllers and everything related to input devices.
|
||||
|
||||
## src/shader_recompiler/
|
||||
|
||||
Dedicated shader recompiler to translate Maxwell assembly code to either SPIR-V, GLSL or GLASM.
|
||||
|
||||
## src/video_core/
|
||||
|
||||
Most of the things here have their own dedicated section. In short this is basically the entire Tegra NVIDIA Maxwell GPU emulation. Additionally it includes some [extra effects](../src/video_core/host_shaders/opengl_smaa.glsl) to emulate MSAA, D24 copies or as polyfill.
|
||||
|
||||
Available backends are: Null, Vulkan, and OpenGL.
|
||||
|
||||
See [NVIDIA GPU](./NvidiaGpu.md).
|
||||
+2
-2
@@ -91,7 +91,7 @@ You may additionally need the `Qt Extension Pack` extension if building Qt.
|
||||
|
||||
# Build speedup
|
||||
|
||||
If you have an HDD, use ramdisk (build in RAM), approximately you need 4GB for a full build with debug symbols:
|
||||
If you have an HDD, use ramdisk (build in RAM), approximatedly you need 4GB for a full build with debug symbols:
|
||||
|
||||
```sh
|
||||
mkdir /tmp/ramdisk
|
||||
@@ -110,7 +110,7 @@ A general rule of thumb, before uploading files:
|
||||
- PNG files: Use [optipng](https://web.archive.org/web/20240325055059/https://optipng.sourceforge.net/).
|
||||
- SVG files: Use [svgo](https://github.com/svg/svgo).
|
||||
|
||||
May not be used but worth mentioning nonetheless:
|
||||
May not be used but worth mentioning nonethless:
|
||||
|
||||
- OGG files: Use [OptiVorbis](https://github.com/OptiVorbis/OptiVorbis).
|
||||
- Video files: Use ffmpeg, preferably re-encode as AV1.
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
|
||||
Are you just a casual user? Take a look at our [User Handbook](./user) then!
|
||||
|
||||
If you want to register/signup as a contributor, take a gander at the [signup guide](https://git.eden-emu.dev/crueter/signup/src/branch/main/README.md).
|
||||
If you want to register/signup as a contributor, take a gander at the [signup guide](./SIGNUP.md).
|
||||
|
||||
This contains documentation created by developers. This contains build instructions, guidelines, instructions/layouts for [cool stuff we made](./CPMUtil), and more.
|
||||
|
||||
@@ -12,14 +12,14 @@ This contains documentation created by developers. This contains build instructi
|
||||
- **[Development Guidelines](./Development.md)**
|
||||
- **[Dependencies](./Deps.md)**
|
||||
- **[Debug Guidelines](./Debug.md)**
|
||||
- **[RenderDoc](./Debug.md#renderdoc)**
|
||||
- **[CPM - CMake Package Manager](./CPMUtil.md)**
|
||||
- **[RenderDoc usage](./RenderDoc.md)**
|
||||
- **[CPM - CMake Package Manager](./CPMUtil)**
|
||||
- **[Platform-Specific Caveats](./Caveats.md)**
|
||||
- **[The NVIDIA SM86 (Maxwell) GPU](./NvidiaGpu.md)**
|
||||
- **[Cross compilation](./CrossCompile.md)**
|
||||
- **[Driver Bugs](./DriverBugs.md)**
|
||||
- **[Building Older Commits](./build/OlderCommits.md)**
|
||||
- Subsystems:
|
||||
- **[Design Overview](./DesignOverview.md)**
|
||||
- **[Dynarmic](./dynarmic/README.md)**
|
||||
- **[HOS Kernel](./HosKernel.md)**
|
||||
- **[Settings](./Settings.md)**
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# RenderDoc
|
||||
|
||||
Renderdoc is a free, cross platform, multi-graphics API debugger. It is an invaluable tool for diagnosing issues with graphics applications, and includes support for Vulkan. Get it at [renderdoc.org](https://renderdoc.org).
|
||||
|
||||
RenderDoc can capture Eden's Vulkan output when its Vulkan layer is loaded before Eden creates the Vulkan device. Before using renderdoc to diagnose issues, it is always good to make sure there are no validation errors. Any errors means the behavior of the application is undefined. That said, renderdoc can help debug validation errors if you do have them.
|
||||
|
||||
## Usage on Windows
|
||||
|
||||
You can either use RenderDoc UI to launch eden, or you can make eden attach it internally:
|
||||
|
||||
On Windows PowerShell:
|
||||
```powershell
|
||||
$env:ENABLE_VULKAN_RENDERDOC_CAPTURE='1'
|
||||
.\eden.exe
|
||||
```
|
||||
When RenderDoc is attached, Eden logs the default Windows capture folder:
|
||||
```text
|
||||
%LOCALAPPDATA%\Temp\RenderDoc
|
||||
```
|
||||
|
||||
Press RenderDoc's capture hotkey, usually `F12`, to capture a frame. To stop using RenderDoc, close Eden and launch it again without `ENABLE_VULKAN_RENDERDOC_CAPTURE`.
|
||||
|
||||
## Eden Hotkey
|
||||
|
||||
Eden also has a separate `Toggle Renderdoc Capture` hotkey behind the debug setting `renderdoc_hotkey`.
|
||||
That hotkey does not load or unload RenderDoc. It only toggles Eden's own manual capture through RenderDoc's API:
|
||||
|
||||
- first press: starts a capture
|
||||
- second press: ends that capture
|
||||
|
||||
## Simple checklist for debugging black screens using Renderdoc
|
||||
|
||||
When debugging a black screen, there are many ways the application could have setup Vulkan wrong.
|
||||
Here is a short checklist of items to look at to make sure are appropriate:
|
||||
|
||||
- Draw call counts are correct (aka not zero, or if rendering many triangles, not 3)
|
||||
- Vertex buffers are bound
|
||||
- vertex attributes are correct - Make sure the size & offset of each attribute matches what should it should be
|
||||
- Any bound push constants and descriptors have the right data - including:
|
||||
- Matrices have correct values - double check the model, view, & projection matrices are uploaded correctly
|
||||
- Pipeline state is correct
|
||||
- viewport range is correct - x,y are 0,0; width & height are screen dimensions, minDepth is 0, maxDepth is 1, NDCDepthRange is 0,1
|
||||
- Fill mode matches expected - usually solid
|
||||
- Culling mode makes sense - commonly back or none
|
||||
- The winding direction is correct - typically CCW (counter clockwise)
|
||||
- Scissor region is correct - usually same as viewport's x,y,width, &height
|
||||
- Blend state is correct
|
||||
- Depth state is correct - typically enabled with Function set to Less than or Equal
|
||||
- Swapchain images are bound when rendering to the swapchain
|
||||
- Image being rendered to is the same as the one being presented when rendering to the swapchain
|
||||
|
||||
Alternatively, a [RenderDoc Extension](https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw) ([Archive](https://web.archive.org/web/20250000000000*/https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw)) exists which automates doing a lot of these manual steps.
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
# Settings
|
||||
|
||||
> [!WARNING]
|
||||
> This guide is intended for developers ONLY. If you're looking for configuring the emulator itself, read **[the user handbook](./user/README.md)**.
|
||||
> This guide is intended for developers ONLY. If you're looking for configuring the emulator itself, please read **[the user handbook](./user/README.md)**.
|
||||
|
||||
Settings on the emulator are very important, toggles and such can be used to guard and/or add branches to paths where some games may crash while others won't, and viceversa.
|
||||
|
||||
However, this process can be tedious for those unfamiliar; this document serves as an outline/documentation for the settings subsystem.
|
||||
However, this process can be tedious for those unfamiliar; this document serves as a outline/documentation for the settings subsystem.
|
||||
|
||||
## Index
|
||||
|
||||
@@ -78,7 +78,7 @@ INSERT(Settings,
|
||||
|
||||
#### Make sure to:
|
||||
|
||||
* Keep display naming consistent
|
||||
* Keep display naming consistant
|
||||
* Put detailed info in the description
|
||||
* Use `\n` for line breaks in descriptions
|
||||
|
||||
@@ -184,7 +184,7 @@ The setting ranges from 0 to 65535 (0x0000 to 0xFFFF), where each bit represents
|
||||
|
||||
### Advantages
|
||||
|
||||
The main advantage is to avoid deploying new disposable toggles (those made only for testing stage, and are disposed once new feature gets good to merge). This empowers devs to be free of all frontend bureaucracy and hassle of new toggles.
|
||||
The main advantage is to avoid deploying new disposable toggles (those made only for testing stage, and are disposed once new feature gets good to merge). This empowers devs to be free of all frontend burocracy and hassle of new toggles.
|
||||
|
||||
Common advantages recap:
|
||||
|
||||
|
||||
+42
-42
@@ -1,44 +1,44 @@
|
||||
# Dynarmic Design Documentation
|
||||
|
||||
Dynarmic is a dynamic recompiler for the ARMv6K architecture. Future plans for Dynarmic include
|
||||
Dynarmic is a dynamic recompiler for the ARMv6K architecture. Future plans for dynarmic include
|
||||
support for other versions of the ARM architecture, having a interpreter mode, and adding support
|
||||
for other architectures.
|
||||
|
||||
Users of this library interact with it primarily through the interface provided in
|
||||
[`src/dynarmic/interface`](../../src/dynarmic/src/dynarmic/interface). Users specify how Dynarmic's CPU core interacts with
|
||||
[`src/dynarmic/interface`](../src/dynarmic/interface). Users specify how dynarmic's CPU core interacts with
|
||||
the rest of their system providing an implementation of the relevant `UserCallbacks` interface.
|
||||
Users setup the CPU state using member functions of `Jit`, then call `Jit::Execute` to start CPU
|
||||
execution. The callbacks defined on `UserCallbacks` may be called from dynamically generated code,
|
||||
so users of the library should not depend on the stack being in a walkable state for unwinding.
|
||||
|
||||
* A32: [`Jit`](../../src/dynarmic/src/dynarmic/interface/A32/a32.h), [`UserCallbacks`](../../src/dynarmic/src/dynarmic/interface/A32/config.h)
|
||||
* A64: [`Jit`](../../src/dynarmic/src/dynarmic/interface/A64/a64.h), [`UserCallbacks`](../../src/dynarmic/src/dynarmic/interface/A64/config.h)
|
||||
* A32: [`Jit`](../src/dynarmic/interface/A32/a32.h), [`UserCallbacks`](../src/dynarmic/interface/A32/config.h)
|
||||
* A64: [`Jit`](../src/dynarmic/interface/A64/a64.h), [`UserCallbacks`](../src/dynarmic/interface/A64/config.h)
|
||||
|
||||
Dynarmic reads instructions from memory by calling `UserCallbacks::MemoryReadCode`. These
|
||||
instructions then pass through several stages:
|
||||
|
||||
1. Decoding (Identifying what type of instruction it is and breaking it up into fields)
|
||||
2. Translation (Generation of high-level IR from the instruction)
|
||||
3. Optimization (Elimination of redundant microinstructions, other speed improvements)
|
||||
3. Optimization (Eliminiation of redundant microinstructions, other speed improvements)
|
||||
4. Emission (Generation of host-executable code into memory)
|
||||
5. Execution (Host CPU jumps to the start of emitted code and runs it)
|
||||
|
||||
Using the A32 frontend with the x64 backend as an example:
|
||||
|
||||
* Decoding is done by [double dispatch](https://en.wikipedia.org/wiki/Visitor_pattern) in
|
||||
[`src/frontend/A32/decoder/{arm.h,thumb16.h,thumb32.h}`](../../src/dynarmic/src/dynarmic/frontend/A32/decoder/).
|
||||
* Translation is done by the visitors in [`src/dynarmic/frontend/A32/translate/translate_{arm,thumb}.cpp`](../../src/dynarmic/src/dynarmic/frontend/A32/translate/).
|
||||
The function [`Translate`](../../src/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp) takes a starting memory location,
|
||||
[`src/frontend/A32/decoder/{arm.h,thumb16.h,thumb32.h}`](../src/dynarmic/frontend/A32/decoder/).
|
||||
* Translation is done by the visitors in [`src/dynarmic/frontend/A32/translate/translate_{arm,thumb}.cpp`](../src/dynarmic/frontend/A32/translate/).
|
||||
The function [`Translate`](../src/dynarmic/frontend/A32/translate/translate.h) takes a starting memory location,
|
||||
some CPU state, and memory reader callback and returns a basic block of IR.
|
||||
* The IR can be found under [`src/frontend/ir/`](../../src/dynarmic/src/dynarmic/ir/).
|
||||
* Optimizations can be found under [`src/ir/opt_passes.cpp`](../../src/dynarmic/src/dynarmic/ir/opt_passes.cpp).
|
||||
* Emission is done by `EmitX64` which can be found in [`src/dynarmic/backend/x64/emit_x64.{h,cpp}`](../../src/dynarmic/src/dynarmic/backend/x64/).
|
||||
* Execution is performed by calling `BlockOfCode::RunCode` in [`src/dynarmic/backend/x64/block_of_code.{h,cpp}`](../../src/dynarmic/src/dynarmic/backend/x64/).
|
||||
* The IR can be found under [`src/frontend/ir/`](../src/dynarmic/ir/).
|
||||
* Optimizations can be found under [`src/ir_opt/`](../src/dynarmic/ir/opt/).
|
||||
* Emission is done by `EmitX64` which can be found in [`src/dynarmic/backend/x64/emit_x64.{h,cpp}`](../src/dynarmic/backend/x64/).
|
||||
* Execution is performed by calling `BlockOfCode::RunCode` in [`src/dynarmic/backend/x64/block_of_code.{h,cpp}`](../src/dynarmic/backend/x64/).
|
||||
|
||||
## Decoder
|
||||
|
||||
The decoder is a double dispatch decoder. Each instruction is represented by a line in the relevant
|
||||
instruction table. Here is an example line from [`arm.h`](../../src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h):
|
||||
instruction table. Here is an example line from [`arm.h`](../src/dynarmic/frontend/A32/decoder/arm.h):
|
||||
|
||||
INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv")
|
||||
|
||||
@@ -61,7 +61,7 @@ error results.
|
||||
## Translator
|
||||
|
||||
The translator is a visitor that uses the decoder to decode instructions. The translator generates IR code with the
|
||||
help of the [`IREmitter` class](../../src/dynarmic/src/dynarmic/ir/ir_emitter.h). An example of a translation function follows:
|
||||
help of the [`IREmitter` class](../src/dynarmic/ir/ir_emitter.h). An example of a translation function follows:
|
||||
|
||||
bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||
@@ -107,7 +107,7 @@ function analyser in the medium-term future.
|
||||
Dynarmic's intermediate representation is typed. Each microinstruction may take zero or more arguments and may
|
||||
return zero or more arguments. A subset of the microinstructions available is documented below.
|
||||
|
||||
A complete list of microinstructions can be found in [src/dynarmic/ir/opcodes.inc](../../src/dynarmic/src/dynarmic/ir/opcodes.inc).
|
||||
A complete list of microinstructions can be found in [src/dynarmic/ir/opcodes.inc](../src/dynarmic/ir/opcodes.inc).
|
||||
|
||||
The below lists some commonly used microinstructions.
|
||||
|
||||
@@ -273,7 +273,7 @@ Exclusive OR (i.e.: XOR)
|
||||
|
||||
### Callback: {Read,Write}Memory{8,16,32,64}
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
<u8> ReadMemory8(<u32> vaddr)
|
||||
<u8> ReadMemory16(<u32> vaddr)
|
||||
<u8> ReadMemory32(<u32> vaddr)
|
||||
@@ -288,7 +288,7 @@ Memory access.
|
||||
|
||||
### Terminal: ReturnToDispatch
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
SetTerm(IR::Term::ReturnToDispatch{})
|
||||
```
|
||||
|
||||
@@ -297,7 +297,7 @@ The dispatcher will use the value in R15 to determine what comes next.
|
||||
|
||||
### Terminal: LinkBlock
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
SetTerm(IR::Term::LinkBlock{next})
|
||||
```
|
||||
|
||||
@@ -307,7 +307,7 @@ dispatcher, which will return control to the host.
|
||||
|
||||
### Terminal: LinkBlockFast
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
SetTerm(IR::Term::LinkBlockFast{next})
|
||||
```
|
||||
|
||||
@@ -316,7 +316,7 @@ This promises guarantees that must be held at runtime - i.e that the program won
|
||||
|
||||
### Terminal: PopRSBHint
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
SetTerm(IR::Term::PopRSBHint{})
|
||||
```
|
||||
|
||||
@@ -328,7 +328,7 @@ this optimization or doesn't have a RSB may choose to implement this exactly as
|
||||
|
||||
### Terminal: If
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
SetTerm(IR::Term::If{cond, term_then, term_else})
|
||||
```
|
||||
|
||||
@@ -366,7 +366,7 @@ Do NEVER modify `%r15`, we must make it clear that this register is "immutable"
|
||||
|
||||
### `Scratch`
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
Xbyak::Reg64 ScratchGpr(HostLocList desired_locations = any_gpr);
|
||||
Xbyak::Xmm ScratchXmm(HostLocList desired_locations = any_xmm);
|
||||
```
|
||||
@@ -375,7 +375,7 @@ At runtime, allocate one of the registers in `desired_locations`. You are free t
|
||||
|
||||
### Pure `Use`
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
Xbyak::Reg64 UseGpr(Argument& arg);
|
||||
Xbyak::Xmm UseXmm(Argument& arg);
|
||||
OpArg UseOpArg(Argument& arg);
|
||||
@@ -391,7 +391,7 @@ This register **must not** have it's value changed.
|
||||
|
||||
### `UseScratch`
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
Xbyak::Reg64 UseScratchGpr(Argument& arg);
|
||||
Xbyak::Xmm UseScratchXmm(Argument& arg);
|
||||
void UseScratch(Argument& arg, HostLoc host_loc);
|
||||
@@ -409,7 +409,7 @@ You are free to modify the value in the register. The register is discarded at t
|
||||
|
||||
A `Define` is the defintion of a value. This is the only time when a value may be set.
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
void DefineValue(IR::Inst* inst, const Xbyak::Reg& reg);
|
||||
```
|
||||
|
||||
@@ -420,7 +420,7 @@ value to the specified register `reg`.
|
||||
|
||||
Adding a `Define` to an existing value.
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
void DefineValue(IR::Inst* inst, Argument& arg);
|
||||
```
|
||||
|
||||
@@ -458,7 +458,7 @@ One complication dynarmic has is that a compiled block is not uniquely identifia
|
||||
the PC alone, but bits in the FPSCR and CPSR are also relevant. We resolve this by
|
||||
computing a 64-bit `UniqueHash` that is guaranteed to uniquely identify a block.
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
u64 LocationDescriptor::UniqueHash() const {
|
||||
// This value MUST BE UNIQUE.
|
||||
// This calculation has to match up with EmitX64::EmitTerminalPopRSBHint
|
||||
@@ -482,18 +482,18 @@ point. Each element in `rsb_location_descriptors` is a `UniqueHash` and they
|
||||
each correspond to an element in `rsb_codeptrs`. `rsb_codeptrs` contains the
|
||||
host addresses for the corresponding the compiled blocks.
|
||||
|
||||
`RSB_SIZE` was chosen by performance testing. Note that this is bigger than the
|
||||
`RSBSize` was chosen by performance testing. Note that this is bigger than the
|
||||
size of the real RSB in hardware (which has 3 entries). Larger RSBs than 8
|
||||
showed degraded performance.
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
struct JitState {
|
||||
// ...
|
||||
|
||||
static constexpr size_t RSB_SIZE = 8; // MUST be a power of 2.
|
||||
static constexpr size_t RSBSize = 8; // MUST be a power of 2.
|
||||
u32 rsb_ptr = 0;
|
||||
std::array<u64, RSB_SIZE> rsb_location_descriptors;
|
||||
std::array<u64, RSB_SIZE> rsb_codeptrs;
|
||||
std::array<u64, RSBSize> rsb_location_descriptors;
|
||||
std::array<u64, RSBSize> rsb_codeptrs;
|
||||
void ResetRSB();
|
||||
|
||||
// ...
|
||||
@@ -505,7 +505,7 @@ struct JitState {
|
||||
We insert our prediction at the insertion point iff the RSB doesn't already
|
||||
contain a prediction with the same `UniqueHash`.
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
void EmitX64::EmitPushRSB(IR::Block&, IR::Inst* inst) {
|
||||
using namespace Xbyak::util;
|
||||
|
||||
@@ -521,7 +521,7 @@ void EmitX64::EmitPushRSB(IR::Block&, IR::Inst* inst) {
|
||||
|
||||
code->mov(index_reg, dword[code.ABI_JIT_PTR + offsetof(JitState, rsb_ptr)]);
|
||||
code->add(index_reg, 1);
|
||||
code->and_(index_reg, u32(JitState::RSB_SIZE - 1));
|
||||
code->and_(index_reg, u32(JitState::RSBSize - 1));
|
||||
|
||||
code->mov(loc_desc_reg, u64(imm64));
|
||||
CodePtr patch_location = code->getCurr<CodePtr>();
|
||||
@@ -530,7 +530,7 @@ void EmitX64::EmitPushRSB(IR::Block&, IR::Inst* inst) {
|
||||
code->EnsurePatchLocationSize(patch_location, 10);
|
||||
|
||||
Xbyak::Label label;
|
||||
for (size_t i = 0; i < JitState::RSB_SIZE; ++i) {
|
||||
for (size_t i = 0; i < JitState::RSBSize; ++i) {
|
||||
code->cmp(loc_desc_reg, qword[code.ABI_JIT_PTR + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]);
|
||||
code->je(label, code->T_SHORT);
|
||||
}
|
||||
@@ -544,12 +544,12 @@ void EmitX64::EmitPushRSB(IR::Block&, IR::Inst* inst) {
|
||||
|
||||
In pseudocode:
|
||||
|
||||
```cpp
|
||||
for (i := 0 .. RSB_SIZE-1)
|
||||
```c++
|
||||
for (i := 0 .. RSBSize-1)
|
||||
if (rsb_location_descriptors[i] == imm64)
|
||||
goto label;
|
||||
rsb_ptr++;
|
||||
rsb_ptr %= RSB_SIZE;
|
||||
rsb_ptr %= RSBSize;
|
||||
rsb_location_desciptors[rsb_ptr] = imm64; //< The UniqueHash
|
||||
rsb_codeptr[rsb_ptr] = /* codeptr corresponding to the UniqueHash */;
|
||||
label:
|
||||
@@ -559,7 +559,7 @@ label:
|
||||
|
||||
To check if a predicition is in the RSB, we linearly scan the RSB.
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
void EmitX64::EmitTerminalPopRSBHint(IR::Term::PopRSBHint, IR::LocationDescriptor initial_location) {
|
||||
using namespace Xbyak::util;
|
||||
|
||||
@@ -571,7 +571,7 @@ void EmitX64::EmitTerminalPopRSBHint(IR::Term::PopRSBHint, IR::LocationDescripto
|
||||
code->or_(rbx, rcx);
|
||||
|
||||
code->mov(rax, u64(code->GetReturnFromRunCodeAddress()));
|
||||
for (size_t i = 0; i < JitState::RSB_SIZE; ++i) {
|
||||
for (size_t i = 0; i < JitState::RSBSize; ++i) {
|
||||
code->cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(JitState, rsb_location_descriptors) + i * sizeof(u64)]);
|
||||
code->cmove(rax, qword[code.ABI_JIT_PTR + offsetof(JitState, rsb_codeptrs) + i * sizeof(u64)]);
|
||||
}
|
||||
@@ -582,10 +582,10 @@ void EmitX64::EmitTerminalPopRSBHint(IR::Term::PopRSBHint, IR::LocationDescripto
|
||||
|
||||
In pseudocode:
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
rbx := ComputeUniqueHash()
|
||||
rax := ReturnToDispatch
|
||||
for (i := 0 .. RSB_SIZE-1)
|
||||
for (i := 0 .. RSBSize-1)
|
||||
if (rbx == rsb_location_descriptors[i])
|
||||
rax = rsb_codeptrs[i]
|
||||
goto rax
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# PowerPC 64 backend
|
||||
|
||||
The ppc64 backend currently only supports the little endian variant, with big endian support being experimental for the time being. Additionally only A32 is supported (for now).
|
||||
|
||||
- Flag handling: Flags are emulated via software, while there may be some funny tricks with the CTR, I'd rather not bother - plus it's widely known that those instructions are not nice on real metal - so I would rather take the i-cache cost.
|
||||
- 128-bit atomics: No 128-bit atomic support is provided, this may cause wrong or erroneous execution in some contexts.
|
||||
|
||||
To handle endianess differences all 16/32/64-bit loads and stores to the "emulated memory" are byteswapped beforehand.
|
||||
+342
-9
@@ -3,20 +3,177 @@ Dynarmic
|
||||
|
||||
A dynamic recompiler for ARM.
|
||||
|
||||
*Note that an adversarial guest program [can determine if it's being ran under Dynarmic](#disadvantages-of-dynarmic). Preventing this is not a goal of this project.*
|
||||
Highlight features:
|
||||
|
||||
Cortex-A57 (32 and 64 bit) is the emulated guest target. See [ArchVersion](../../src/dynarmic/src/dynarmic/interface/A32/arch_version.h).
|
||||
- Fast dynamic binary translation via Just-in-Time compilation
|
||||
- Clean API
|
||||
- Implemented in modern C++20
|
||||
- Hooks exposed for easy code instrumentation
|
||||
- Code injection support for very fine-grained instrumentation
|
||||
- Support for unusual address space setups (bring-your-own memory system)
|
||||
- Native support for most popular operating systems (Windows, macOS, Linux, FreeBSD, OpenBSD, NetBSD, Android)
|
||||
|
||||
The only supported host architectures are x86-64, and AArch64. There are no plans to support any 32-bit architectures.
|
||||
*Please note that an adversarial guest program [can determine if it is being run under dynarmic](#disadvantages-of-dynarmic). Preventing this is not a goal of this project.*
|
||||
|
||||
See [an example usage](../../src/dynarmic/tests/print_info.cpp).
|
||||
### Supported guest architectures
|
||||
|
||||
* v3
|
||||
* v4
|
||||
* v4T
|
||||
* v5TE
|
||||
* v6K
|
||||
* v6T2
|
||||
* v7A
|
||||
* 32-bit v8
|
||||
* 64-bit v8
|
||||
|
||||
You can specify the specific guest version using [ArchVersion](src/dynarmic/interface/A32/arch_version.h).
|
||||
|
||||
There are no plans to support v1 or v2.
|
||||
|
||||
### Supported host architectures
|
||||
|
||||
* x86-64
|
||||
* AArch64
|
||||
* PowerPC 64 (POWER 4 and up)
|
||||
|
||||
There are no plans to support any 32-bit architecture.
|
||||
|
||||
Important API Changes in v6.x Series
|
||||
------------------------------------
|
||||
|
||||
* **v6.7.0**
|
||||
* To support use cases where one wants to have the guest to have the same address space as the host, `nullptr` is now a valid value for `fastmem_pointer`.
|
||||
**This change is not backwards-compatible.** If you were previously using `nullptr` to represent an invalid fastmem arena, you will now have to use `std::nullopt`.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Design documentation can be found at [./Design.md](./Design.md).
|
||||
PowerPC design documentation can be found at [./PowerPC](./PowerPC.md).
|
||||
|
||||
|
||||
Usage Example
|
||||
-------------
|
||||
|
||||
The below is a minimal example. Bring-your-own memory system.
|
||||
|
||||
```cpp
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <exception>
|
||||
|
||||
#include "dynarmic/interface/A32/a32.h"
|
||||
#include "dynarmic/interface/A32/config.h"
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
|
||||
class MyEnvironment final : public Dynarmic::A32::UserCallbacks {
|
||||
public:
|
||||
u64 ticks_left = 0;
|
||||
std::array<u8, 2048> memory{};
|
||||
|
||||
u8 MemoryRead8(u32 vaddr) override {
|
||||
if (vaddr >= memory.size()) {
|
||||
return 0;
|
||||
}
|
||||
return memory[vaddr];
|
||||
}
|
||||
|
||||
u16 MemoryRead16(u32 vaddr) override {
|
||||
return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8;
|
||||
}
|
||||
|
||||
u32 MemoryRead32(u32 vaddr) override {
|
||||
return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16;
|
||||
}
|
||||
|
||||
u64 MemoryRead64(u32 vaddr) override {
|
||||
return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32;
|
||||
}
|
||||
|
||||
void MemoryWrite8(u32 vaddr, u8 value) override {
|
||||
if (vaddr >= memory.size()) {
|
||||
return;
|
||||
}
|
||||
memory[vaddr] = value;
|
||||
}
|
||||
|
||||
void MemoryWrite16(u32 vaddr, u16 value) override {
|
||||
MemoryWrite8(vaddr, u8(value));
|
||||
MemoryWrite8(vaddr + 1, u8(value >> 8));
|
||||
}
|
||||
|
||||
void MemoryWrite32(u32 vaddr, u32 value) override {
|
||||
MemoryWrite16(vaddr, u16(value));
|
||||
MemoryWrite16(vaddr + 2, u16(value >> 16));
|
||||
}
|
||||
|
||||
void MemoryWrite64(u32 vaddr, u64 value) override {
|
||||
MemoryWrite32(vaddr, u32(value));
|
||||
MemoryWrite32(vaddr + 4, u32(value >> 32));
|
||||
}
|
||||
|
||||
void CallSVC(u32 swi) override {
|
||||
// Do something.
|
||||
}
|
||||
|
||||
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
|
||||
// Do something.
|
||||
}
|
||||
|
||||
void AddTicks(u64 ticks) override {
|
||||
if (ticks > ticks_left) {
|
||||
ticks_left = 0;
|
||||
return;
|
||||
}
|
||||
ticks_left -= ticks;
|
||||
}
|
||||
|
||||
u64 GetTicksRemaining() override {
|
||||
return ticks_left;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MyEnvironment env;
|
||||
Dynarmic::A32::UserConfig user_config;
|
||||
user_config.callbacks = &env;
|
||||
Dynarmic::A32::Jit cpu{user_config};
|
||||
|
||||
// Execute at least 1 instruction.
|
||||
// (Note: More than one instruction may be executed.)
|
||||
env.ticks_left = 1;
|
||||
|
||||
// Write some code to memory.
|
||||
env.MemoryWrite16(0, 0x0088); // lsls r0, r1, #2
|
||||
env.MemoryWrite16(2, 0xE7FE); // b +#0 (infinite loop)
|
||||
|
||||
// Setup registers.
|
||||
cpu.Regs()[0] = 1;
|
||||
cpu.Regs()[1] = 2;
|
||||
cpu.Regs()[15] = 0; // PC = 0
|
||||
cpu.SetCpsr(0x00000030); // Thumb mode
|
||||
|
||||
// Execute!
|
||||
cpu.Run();
|
||||
|
||||
// Here we would expect cpu.Regs()[0] == 8
|
||||
printf("R0: %u\n", cpu.Regs()[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Alternatives to Dynarmic
|
||||
------------------------
|
||||
|
||||
Here are some projects with the same goals as Dynarmic:
|
||||
Here are some projects with the same goals as dynarmic:
|
||||
|
||||
* [Unicorn](https://www.unicorn-engine.org/) - Recompiling multi-architecture CPU emulator, based on QEMU
|
||||
* [SkyEye](http://skyeye.sourceforge.net) - Cached interpreter for ARM
|
||||
@@ -34,8 +191,8 @@ More general alternatives:
|
||||
Disadvantages of Dynarmic
|
||||
-------------------------
|
||||
|
||||
In the pursuit of speed, some behavior not commonly depended upon is elided. Hence this emulator doesn't match spec.
|
||||
Note that this would mean that a guest application can easily determine if it's being ran under instrumentation.
|
||||
In the pursuit of speed, some behavior not commonly depended upon is elided. Therefore this emulator does not match spec.
|
||||
Please note that this would mean that a guest application can easily determine if it is being run under instrumentation.
|
||||
|
||||
Known examples:
|
||||
|
||||
@@ -50,6 +207,182 @@ Use this code base at your own risk.
|
||||
Legal
|
||||
-----
|
||||
|
||||
Dynarmic is under a GPLv3 license, check the relevant file headers for more information.
|
||||
dynarmic is under a 0BSD license. See LICENSE.txt for more details.
|
||||
|
||||
Dynarmic uses several open-source libraries, whose licenses are included inside thereof.
|
||||
dynarmic uses several other libraries, whose licenses are included below:
|
||||
|
||||
### biscuit
|
||||
|
||||
```
|
||||
Copyright 2021 Lioncash/Lioncache
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
```
|
||||
|
||||
### catch
|
||||
|
||||
```
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
|
||||
### fmt
|
||||
|
||||
```
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### mcl & oaknut
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 merryhime <https://mary.rs>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
### unordered_dense
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Martin Leitner-Ankerl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
### xbyak
|
||||
|
||||
```
|
||||
Copyright (c) 2007 MITSUNARI Shigeo
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
Neither the name of the copyright owner nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-----------------------------------------------------------------------------
|
||||
ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満た
|
||||
す場合に限り、再頒布および使用が許可されます。
|
||||
|
||||
ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項
|
||||
を含めること。
|
||||
バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作
|
||||
権表示、本条件一覧、および下記免責条項を含めること。
|
||||
書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進
|
||||
に、著作権者の名前またはコントリビューターの名前を使用してはならない。
|
||||
本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供さ
|
||||
れており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性
|
||||
に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありません。
|
||||
著作権者もコントリビューターも、事由のいかんを問わず、 損害発生の原因いかんを
|
||||
問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法行為で
|
||||
あるかを問わず、仮にそのような損害が発生する可能性を知らされていたとしても、
|
||||
本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、使用の
|
||||
喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されない)直接
|
||||
損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害について、
|
||||
一切責任を負わないものとします。
|
||||
```
|
||||
|
||||
@@ -24,8 +24,8 @@ Everyone has their own way of viewing good/bad C++ practices, my general outline
|
||||
- Exploit the fact `std::atomic<uint32_t>/std::atomic<int32_t>` is basically free on most arches that matter.
|
||||
- In x86_64, an atomic `uint32_t` is basically `mov [m32], r32`, which is essentially free/cheap.
|
||||
- Avoid template parameters unless you really need them.
|
||||
- For small inline-able functions this is fine, for more complex ones, consider the generated assembly.
|
||||
- Don't make your own memcpy/memset/strcpy/strncpy/etc.
|
||||
- For small inlineable functions this is fine, for more complex ones, please consider the generated assembly.
|
||||
- Dont make your own memcpy/memset/strcpy/strncpy/etc.
|
||||
- Seriously DON'T DO THIS. You will NOT beat the compiler.
|
||||
- Nor 30 years of writing optimized `mem*`.
|
||||
- If your code is slow, don't blame `mem*`, blame your code.
|
||||
@@ -37,7 +37,7 @@ Everyone has their own way of viewing good/bad C++ practices, my general outline
|
||||
- Function parameters are cheap. Don't be afraid to use as many as needed (API usability permitting).
|
||||
- Don't save a reference in structures of a parent object, i.e:
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
struct Child {
|
||||
Parent& parent;
|
||||
void Mehod() {
|
||||
@@ -48,7 +48,7 @@ Everyone has their own way of viewing good/bad C++ practices, my general outline
|
||||
|
||||
- Instead you can do the following:
|
||||
|
||||
```cpp
|
||||
```c++
|
||||
struct Child {
|
||||
void Mehod(Parent& parent) {
|
||||
parent.Something();
|
||||
@@ -66,6 +66,6 @@ Programming, alongside the physical act of writing code, also consists of archit
|
||||
- Dependencies that are legitimately useful to have are few and far between.
|
||||
- At the same time, NIHing your own implementations of widely adopted algorithms or standards can be quite subpar.
|
||||
- For dependencies that are very large but contain something you need, consider cherry-picking the individual files it needs (or writing a smaller version of it)
|
||||
- Try to rely less on indirection for architecting systems
|
||||
- Try to rely less on indirection for architecturing systems
|
||||
- If the underlying HLE kernel emulation requires it, try making a solution that keeps things local
|
||||
- For example, there isn't a need for file descriptors to each be a pointer, when they could be a fixed table size with elements that may be emplaced at will.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this guide whenever you want to modify the Date or Time that Eden reports to games. This can be useful for modifying RNG elements, skipping wait times in games, etc.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Setting-a-Custom-Date-Time-in-Eden-2b357c2edaf680acb8d4e63ccc126564) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Setting-a-Custom-Date-Time-in-Eden-2b357c2edaf680acb8d4e63ccc126564) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
|
||||
+12
-30
@@ -44,7 +44,7 @@ Only Fedora/riscv64 has been tested, but in theory, every riscv64 distribution t
|
||||
|
||||
## Other
|
||||
|
||||
Other architectures, such as SPARC, MIPS, PowerPC, Loong, and all 32-bit architectures are completely unsupported, as there is no JIT backend or emitter thereof. If you want support for it -- submit patches!
|
||||
Other architectures, such as SPARC, MIPS, PowerPC, Loong, and all 32-bit architectures are completely unsupported, as there is no JIT backend or emitter thereof. If you want support for it--submit patches!
|
||||
|
||||
IA-64 (Itanium) support is completely unknown. Existing amd64 packages will not run on IA-64 (assuming you can even find a supported Windows/Linux distribution)
|
||||
|
||||
@@ -52,18 +52,18 @@ IA-64 (Itanium) support is completely unknown. Existing amd64 packages will not
|
||||
|
||||
The vast majority of Eden's testing is done on Windows, Linux, and Android. However, first-class support is also provided for:
|
||||
|
||||
- FreeBSD (amd64, aarch64)
|
||||
- HaikuOS (amd64)
|
||||
- OpenBSD (amd64)
|
||||
- NetBSD (amd64)
|
||||
- macOS (aarch64)
|
||||
- OpenIndiana aka. OpenSolaris (amd64)
|
||||
- HaikuOS
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- OpenIndiana (Solaris)
|
||||
- macOS
|
||||
|
||||
## Linux
|
||||
|
||||
While all modern Linux distributions are supported (Fedora >40, Ubuntu >24.04, Debian >12, Arch, Gentoo, etc.), the vast majority of testing and development for Linux is on Arch and Gentoo. Most major build system changes are tested on Gentoo first and foremost, so if builds fail on any modern distribution no matter what you do, it's likely a bug and should be reported.
|
||||
|
||||
Intel and NVIDIA GPU support is limited. AMD (RADV) drivers receive first-class testing and are known to provide the most stable Eden experience possible.
|
||||
Intel and Nvidia GPU support is limited. AMD (RADV) drivers receive first-class testing and are known to provide the most stable Eden experience possible.
|
||||
|
||||
Wayland is not recommended. Testing has shown significantly worse performance on most Wayland compositors compared to X11, alongside mysterious bugs and compatibility errors. For now, set `QT_QPA_PLATFORM=xcb` when running Eden, or pass `-platform xcb` to the launch arguments.
|
||||
|
||||
@@ -73,25 +73,7 @@ Windows 10 and 11 are supported. Support for Windows 8.x is unknown, and Windows
|
||||
|
||||
In order to run Eden, you will probably need to install the [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170).
|
||||
|
||||
Neither AMD/NVIDIA drivers work nearly as well as Linux's RADV drivers. Compatibility is still largely the same, but performance and some hard-to-run games may suffer compared to Linux.
|
||||
|
||||
Tacit support for down to XP is provided for interested hobbyists. Read below.
|
||||
|
||||
### Windows 7, 8, 8.1
|
||||
|
||||
DirectX 12 is not available - simply copy and paste any DLL and name it `d3d12.dll`.
|
||||
|
||||
Install [Qt6 compatibility libraries](https://github.com/crystalidea/qt6windows7) specifically Qt 6.9.5.
|
||||
|
||||
### Windows XP, Vista
|
||||
|
||||
If you haven't already, install appropriate updates using [Legacy Update](https://legacyupdate.net/). We highly recommend to install [One-Core-API](https://github.com/shorthorn-project/One-Core-API-Binaries) as well.
|
||||
|
||||
64-bit support is *mandatory*, there are no plans to add 32-bit support (PRs are welcome of course). While AVX2 support is recommended, it isn't a hard requirement. SSE4.1+ is recommended however, while the emulator does run well without (minimum is SSE3), non-SSE4.1 code paths are unmaintained.
|
||||
|
||||
### Windows on ARM
|
||||
|
||||
If you're using Snapdragon X or 8CX, use the [the Vulkan translation layer](https://apps.microsoft.com/detail/9nqpsl29bfff?hl=en-us&gl=USE) only if the stock drivers do not work. And of course always keep your system up-to-date.
|
||||
Neither AMD nor Nvidia drivers work nearly as well as Linux's RADV drivers. Compatibility is still largely the same, but performance and some hard-to-run games may suffer compared to Linux.
|
||||
|
||||
## Android
|
||||
|
||||
@@ -141,13 +123,13 @@ Do note that building the GUI version with Qt versions higher than 6.7.3 will ca
|
||||
|
||||
## *BSD, Solaris
|
||||
|
||||
BSD and Solaris distributions tend to lag behind Linux in terms of Vulkan and ports. For example, OpenIndiana (Solaris) does not properly package Qt, meaning the recommended method of usage is to use `eden-cli` for now. Solaris also generally works better with OpenGL.
|
||||
BSD and Solaris distributions tend to lag behind Linux in terms of Vulkan and other library compatibility. For example, OpenIndiana (Solaris) does not properly package Qt, meaning the recommended method of usage is to use `eden-cli` only for now. Solaris also generally works better with OpenGL.
|
||||
|
||||
AMD GPU support on these platforms is limited or nonexistent, bar for OpenBSD which has a dedicated AMD GPU stack.
|
||||
AMD GPU support on these platforms is limited or nonexistent.
|
||||
|
||||
## HaikuOS
|
||||
|
||||
HaikuOS supports (see below) Vulkan 1.3 and has Mesa 24.0. Because OpenGL ES is used instead of the desktop flavour of OpenGL the OpenGL backend is actually worse than the Vulkan one in terms of stability and system support. OpenGL is highly not recommended due to it being out of tree builds of Mesa and generally unstable ones at that. Users are advised to use Vulkan instead.
|
||||
HaikuOS supports (see below) Vulkan 1.3 and has Mesa 24.0. Because OpenGL ES is used instead of the desktop flavour of OpenGL the OpenGL backend is actually worse than the Vulkan one in terms of stability and system support. OpenGL is highly not recommended due to it being: out of tree builds of Mesa and generally unstable ones at that. Users are advised to use Vulkan whenever possible.
|
||||
|
||||
- Additionally system drivers for NVIDIA and Intel iGPUs exist and provide a native Vulkan ICD with the `Xcb` interface as opposed to the native `BView`
|
||||
- In order to obtain Vulkan 1.3 support with native `BView` support; Swiftshader can be compiled from source [see this thread](https://discuss.haiku-os.org/t/swiftshader-vulkan-software-renderer-on-haiku/11526/6).
|
||||
|
||||
+4
-4
@@ -22,8 +22,8 @@ If your GPU doesn't support or is just behind by a minor version, see Mesa envir
|
||||
- RC releases: Release candidate, generally "less stable but still stable" versions.
|
||||
- Full release: "The stablest possible you could get".
|
||||
- Nightly: Builds done around 2PM UTC (if there are any changes), generally stable, but not recommended for the average user. These contain daily updates and may contain critical fixes for some games.
|
||||
- Master: Unstable builds, can range from games working exceptionally well to instantly crashing. These contain straight from the oven fixes, don't use them unless you plan to contribute something! They're very experimental! Still 95% of the time they will work just fine.
|
||||
- PR builds: Highly experimental builds, testers may grab from these. The average user should treat them the same as master builds.
|
||||
- Master: Unstable builds, can lead from a game working exceptionally fine to absolute crashing in some systems because someone forgot to check if NixOS or Solaris worked. These contain straight from the oven fixes, please don't use them unless you plan to contribute something! They're very experimental! Still 95% of the time it will work just fine.
|
||||
- PR builds: Highly experimental builds, testers may grab from these. The average user should treat them the same as master builds, except sometimes they straight up don't build/work.
|
||||
|
||||
## User configuration
|
||||
|
||||
@@ -36,7 +36,7 @@ Eden will store configuration files in the following directories:
|
||||
- **Linux, macOS, FreeBSD, Solaris, OpenBSD**: `$XDG_DATA_HOME`, `$XDG_CACHE_HOME`, `$XDG_CONFIG_HOME`.
|
||||
- **HaikuOS**: `/boot/home/config/settings/eden`
|
||||
|
||||
If a `user` directory is present in the current working directory, that will override all global configuration directories and the emulator will use the `user` directory instead.
|
||||
If a `user` directory is present in the current working directory, that will override all global configuration directories and the emulator will use that instead.
|
||||
|
||||
### Environment variables
|
||||
|
||||
@@ -64,4 +64,4 @@ Then just running `chmod +x script.sh && source script.sh`.
|
||||
|
||||
## Compatibility list
|
||||
|
||||
Eden doesn't maintain a compatibility list. However, [EmuReady](https://www.emuready.com/) has a more fine-grained compatibility information for multiple emulators/forks as well.
|
||||
Eden doesn't mantain a compatibility list. However, [EmuReady](https://www.emuready.com/) has a more fine-grained compatibility information for multiple emulators/forks as well.
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ If they don't run - then that's a bug!
|
||||
|
||||
## Atmosphere
|
||||
|
||||
Fusee-Galee, the bootloader and other low-level mechanisms are not emulated at the moment.
|
||||
Fusee Galee, the bootloader and other low-level mechanisms are not emulated at the moment.
|
||||
|
||||
Having OFW is recommended, but may not be required (untested).
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ There are two main applications, an SDL-based app (`eden-cli`) and a Qt based ap
|
||||
|
||||
## eden
|
||||
|
||||
- `./eden <path>`: Running with a single argument and nothing else, will make the emulator look for the given file and load it, this behavior is similar to `eden-cli`; allows dragging and dropping games into the application.
|
||||
- `./eden <path>`: Running with a single argument and nothing else, will make the emulator look for the given file and load it, this behaviour is similar to `eden-cli`; allows dragging and dropping games into the application.
|
||||
- `-g <path>`: Alternate way to specify what to load, overrides. However let it be noted that arguments that use `-` will be treated as options/ignored, if your game, for some reason, starts with `-`, in order to safely handle it you may need to specify it as an argument.
|
||||
- `-f`: Use fullscreen.
|
||||
- `-u <number>`: Select the index of the user to load as.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# User Handbook - Controllers
|
||||
|
||||
Most of the controls should work out of the box. If not, use a joystick calibrator to ensure it's not an issue with your own controller, for example:
|
||||
Most of the controls should work out of the box. If not, please use a joystick calibrator to ensure it's not an issue with your own controller, for example:
|
||||
|
||||
- https://github.com/dkosmari/calibrate-joystick
|
||||
|
||||
## Using external controllers on the Steamdeck
|
||||
|
||||
In desktop mode ignore your Pro controller/XBOX controller external controller and use **Steam Virtual Gamepad 0 as Player 1**. If you have multiple external controllers set **Player 2 to Steam Virtual Gamepad 1**. Steam app must not be closed on desktop mode.
|
||||
In desktop mode ignore your pro controller/xbox contoller external controller and use **Steam Virtual Gamepad 0 as Player 1**. If you have multiple external controllers set **Player 2 to Steam Virtual Gamepad 1**. Steam app must not be closed on desktop mode.
|
||||
|
||||
Here's the annoying part of it. When waking up the steam deck from sleep try not to touch any button on the Steamdeck and turn on your external controller. Then open the Eden.AppImage. If you're lucky you can get your external controller to be position 0 and also Steam Virtual Gamepad 0 in desktop mode. If not that is ok too unless you need to configure player 1 to have gyro. You might need to repeat this to get your external controller as Steam Virtual Gamepad 0 so you can config Player 1 having gyro. You might be able to config player 1 to have gyro with the Steamdeck itself. Or you can also config player 1, 2, 3, etc, to have gyro somehow. Make sure they are all using Virtual Gamepads though.
|
||||
|
||||
@@ -18,7 +18,7 @@ Basically the Steamdeck or the external controller is fighting for position 0 an
|
||||
|
||||
Use this guide for when you want to configure specific controller settings to be reused.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Configuring-Controller-Profiles-2be57c2edaf680eabc3ac8c333ec75c4) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Configuring-Controller-Profiles-2be57c2edaf680eabc3ac8c333ec75c4) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
@@ -30,8 +30,8 @@ Use this guide for when you want to configure specific controller settings to be
|
||||
|
||||
#### Steps
|
||||
1. Launch Eden and wait for it to load.
|
||||
2. Navigate to `Emulation > Configure...`
|
||||
3. Select **Controls** from the left-hand menu and configure your controller for the way you want it to be in-game.
|
||||
2. Navigate to *Emulation > Configure...*
|
||||
3. Select **Controls** from the left-hand menu and configure your controller for the way you want it to be in game.
|
||||
4. Select **New** and enter a name for the profile in the box that appears. Press **OK** to save the profile settings.
|
||||
5. Select **OK** to close the settings menu.
|
||||
|
||||
@@ -39,7 +39,7 @@ Use this guide for when you want to configure specific controller settings to be
|
||||
|
||||
Use this guide when you want to set up specific controller profiles for specific games. This can be useful for certain games like *Captain Toad Treasure Tracker* where a blue dot appears in the middle of the screen when you have docked mode enabled, but not handheld mode.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Setting-Controller-Profiles-By-Game-2b057c2edaf681658a57f0c199cb6083) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Setting-Controller-Profiles-By-Game-2b057c2edaf681658a57f0c199cb6083) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
@@ -47,6 +47,7 @@ Use this guide when you want to set up specific controller profiles for specific
|
||||
|
||||
- Eden Emulator set up and fully configured
|
||||
- Controller Profile Created
|
||||
- See [*Configuring Controller Profiles*](./ControllerProfiles.md) for instructions on how to do this if needed.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ HaikuOS bundles a Mesa library that doesn't support full core OpenGL 4.6 (requir
|
||||
### Fixes for Windows 10 and above having "Device loss"
|
||||
|
||||
Run the following batch script *inside* the Eden folder:
|
||||
```bat
|
||||
```cmd
|
||||
@echo off
|
||||
pushd "%~dp0"
|
||||
if exist "%temp%\FixFullScreen.reg" (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Getting Gyro/Motion Controls Working on Steam Deck
|
||||
Use this guide when you want to use the Steam Deck's native gyro functionality for motion controls in Eden.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Getting-Gyro-Motion-Controls-Working-on-Steam-Deck-2b057c2edaf681a1aaade35db6e0fd1b) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Getting-Gyro-Motion-Controls-Working-on-Steam-Deck-2b057c2edaf681a1aaade35db6e0fd1b) for a version of this guide with images & visual elements.**
|
||||
|
||||
## Steamdeck
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this when you need to review the logs to determine an issue or provide them to a member of the Eden team.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/How-to-Access-Logs-2b057c2edaf68105a281fe1688a332d4) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/How-to-Access-Logs-2b057c2edaf68105a281fe1688a332d4) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this guide when you want to manually import save files for use in the Eden emulator.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Importing-Saves-Into-Eden-2b057c2edaf681fe968df8d63821ccae) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Importing-Saves-Into-Eden-2b057c2edaf681fe968df8d63821ccae) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Pre-Requisites
|
||||
- Eden emulator already set up and configured.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this guide for when you want to install an Atmosphere-based mod for use in Eden.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Installing-Atmosphere-Mods-2b057c2edaf681fe8d39cbfc2d0cc799) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Installing-Atmosphere-Mods-2b057c2edaf681fe8d39cbfc2d0cc799) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Use this guide when you want to install Updates or DLC for your games in Eden.
|
||||
|
||||
</aside>
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Working-with-Updates-DLC-in-Eden-2b057c2edaf681dfb65dfc4dd96980c0) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Working-with-Updates-DLC-in-Eden-2b057c2edaf681dfb65dfc4dd96980c0) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
|
||||
+12
-12
@@ -4,7 +4,7 @@ Use this guide to answer questions regarding and to start using the multiplayer
|
||||
## Multiplayer FAQ
|
||||
This FAQ will serve as a general quick question and answer simple questions.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Multiplayer-FAQ-2c357c2edaf680fca2e9ce59969a220f) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Multiplayer-FAQ-2c357c2edaf680fca2e9ce59969a220f) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Can Eden Play Games with a Switch Console?
|
||||
No - The only emulator that has this kind of functionality is *Ryujinx* and it's forks. This solution requires loading a custom module on a modded switch console to work.
|
||||
@@ -40,7 +40,7 @@ While it would be nice if everything always worked perfectly - that is not reali
|
||||
1. Emulator Version Mismatches
|
||||
1. Occasionally updates to the emulator of choice alter how the LDN functionality is handled. In these situations, unexpected behavior can occur when trying to establish LDN connections. This is a good first step to check if you are having issues playing a game together, but can join the same lobby without issue.
|
||||
2. Game Version Mismatches
|
||||
1. It is best practice to have the game version be identical to each other in order to ensure that there is no difference in how the programs are handling the LDN logic. Games are black boxes that the dev team can't see into to ensure the logic handling operates the same way. For this reason, it is highly advised that the game versions match across all the players. This would be a good 2nd step to check if you are having issues playing a game together, but can join the same lobby without issue.
|
||||
1. It is best practice to have the game version be identical to each other in order to ensure that there is no difference in how the programs are handling the LDN logic. Games are black boxes that the dev team cannot see into to ensure the logic handling operates the same way. For this reason, it is highly advised that the game versions match across all the players. This would be a good 2nd step to check if you are having issues playing a game together, but can join the same lobby without issue.
|
||||
3. Latency
|
||||
1. Because this implementation is emulating a LAN/Local Wireless connection - it is extremely sensitive to network latency and drops. Eden has done a good job of trying to account for this and not immediately drop users out - but it is not infallible. If latency is a concern or becomes an issue - consider hosting a room.
|
||||
|
||||
@@ -49,7 +49,7 @@ While it would be nice if everything always worked perfectly - that is not reali
|
||||
## Joining a Multiplayer Room
|
||||
Use this when you need to connect to a multiplayer room for LDN functionality inside of Eden. This does not cover how to host a room, only joining existing ones.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Pre-Requisites
|
||||
- Eden set up and functioning
|
||||
@@ -66,7 +66,7 @@ There are 2 primary methods that you can use to connect to an existing room, dep
|
||||
|
||||
<aside>
|
||||
|
||||
***NOTE:*** Just because a lobby appears on the public lobby list, does not mean that the host has properly configured the necessary port forwarding/firewall rules to allow a connection. If you can't connect to a lobby, move onto another entry as the issue is probably not on your end. Start looking at your environment if you are unable to connect to multiple/any lobbies.
|
||||
***NOTE:*** Just because a lobby appears on the public lobby list, does not mean that the hoster has properly configured the necessary port forwarding/firewall rules to allow a connection. If you cannot connect to a lobby, move onto another entry as the issue is probably not on your end. Start looking at your environment if you are unable to connect to multiple/any lobbies.
|
||||
|
||||
</aside>
|
||||
|
||||
@@ -82,10 +82,10 @@ There are 2 primary methods that you can use to connect to an existing room, dep
|
||||
3. You will now see a window showing everyone on the lobby, or an error message.
|
||||
|
||||
### Direct Connecting to a Room
|
||||
If the host has not made the lobby public, or you don't want to find it in the public game browser - use this option to connect.
|
||||
If the hoster has not made the lobby public, or you don't want to find it in the public game browser - use this option to connect.
|
||||
|
||||
1. Open Eden and navigate to *Multiplayer > Direct Connect*.
|
||||
2. Enter the *Server Address, Port*, *Nickname* (what your user will be called in the room), and a *Password* (if the host set one, otherwise leave it blank) and hit **Connect.**
|
||||
2. Enter the *Server Address, Port*, *Nickname* (what your user will be called in the room), and a *Password* (if the hoster set one, otherwise leave it blank) and hit **Connect.**
|
||||
3. You will now see a window showing everyone on the lobby, or an error message.
|
||||
|
||||
---
|
||||
@@ -93,7 +93,7 @@ If the host has not made the lobby public, or you don't want to find it in the p
|
||||
## Hosting a Multiplayer Room
|
||||
Use this guide for when you want to host a multiplayer lobby to play with others in Eden. In order to have someone access the room from outside your local network, see the *Access Your Multiplayer Room Externally* section for next steps.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Hosting-a-Multiplayer-Room-2c357c2edaf6819481dbe8a99926cea2) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Hosting-a-Multiplayer-Room-2c357c2edaf6819481dbe8a99926cea2) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Pre-Requisites
|
||||
- Eden set up and Functioning
|
||||
@@ -123,7 +123,7 @@ Use this guide for when you want to host a multiplayer lobby to play with others
|
||||
## Access Your Multiplayer Room Externally
|
||||
Quite often the person with whom you want to play is located off of your internal network (LAN). If you want to host a room and play with them you will need to get your devices to communicate with each other. This guide will go over your options on how to do this so that you can play together.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Pre-Requisites
|
||||
- Eden set up and Functioning
|
||||
@@ -137,7 +137,7 @@ Quite often the person with whom you want to play is located off of your interna
|
||||
|
||||
<aside>
|
||||
|
||||
Use this option if you want the greatest performance/lowest latency, don't want to install any software, and have the ability to modify your networking equipment's configuration (most notably - your router). Avoid this option if you can't modify your router's configuration or are uncomfortable with looking up things on your own.
|
||||
Use this option if you want the greatest performance/lowest latency, don't want to install any software, and have the ability to modify your networking equipment's configuration (most notably - your router). Avoid this option if you cannot modify your router's configuration or are uncomfortable with looking up things on your own.
|
||||
|
||||
</aside>
|
||||
|
||||
@@ -155,7 +155,7 @@ Remember you can't have one port open for multiple devices at the same time - yo
|
||||
|
||||
<aside>
|
||||
|
||||
Use this option if you don't want to have to worry about other users machine/configuration settings, but also can't do port forwarding. This will still require that you as the host install a program and sign up for an account - but will prevent you from having to deal with port forwards or networking equipment. Avoid this option if there is not a close relay and you are getting issues with latency.
|
||||
Use this option if you don't want to have to worry about other users machine/configuration settings, but also cannot do port forwarding. This will still require that you as the hoster install a program and sign up for an account - but will prevent you from having to deal with port forwards or networking equipment. Avoid this option if there is not a close relay and you are getting issues with latency.
|
||||
|
||||
</aside>
|
||||
|
||||
@@ -193,7 +193,7 @@ The VPN solution is a good compromise between the tunnelling solution and port f
|
||||
## Finding the Server Information for a Multiplayer Room
|
||||
Use this guide when you need to determine the connection information for the Public Multiplayer Lobby you are connected to.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Finding-the-Server-Information-for-a-Multiplayer-Room-2c557c2edaf6809e94e8ed3429b9eb26) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Finding-the-Server-Information-for-a-Multiplayer-Room-2c557c2edaf6809e94e8ed3429b9eb26) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Pre-Requisites
|
||||
- Eden set up and configured
|
||||
@@ -256,7 +256,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||
## Multiplayer for Local Co-Op Games
|
||||
Use this guide when you want to play with a friend on a different system for games that only support local co-op.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Multiplayer-for-Local-Co-Op-Games-2c657c2edaf680c59975ec6b52022a2d) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Multiplayer-for-Local-Co-Op-Games-2c657c2edaf680c59975ec6b52022a2d) for a version of this guide with images & visual elements.**
|
||||
|
||||
Occasionally you will want to play a game with a friend on a game that does not support LDN multiplayer, and only offer local co-op (multiple controllers connected to a single console), such as with *New Super Mario Bros. U Deluxe.* Emulation solutions have developed 2 primary methods for handling these cases.
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
# User Handbook - Native Application Development
|
||||
|
||||
Debugging on physical hardware can get tedious and time consuming. Users are empowered with the debugging capabilities of the emulator to ensure their applications run as-is on the system. To the greatest extent possible at least.
|
||||
Debugging on physical hardware can get tedious and time consuming. Users are empowered with the debugging capabilities of the emulator to ensure their applications run as-is on the system. To the greatest extent possible atleast.
|
||||
|
||||
## Debugging
|
||||
|
||||
**Standard key prefix**: Allows to redirect the key manager to a file other than `prod.keys` (for example `other` would redirect to `other.keys`). This is useful for testing multiple keysets. Default is `prod`.
|
||||
|
||||
**Changing serial**: Very basic way to set debug values for the serial (and battery number). Developers do not need to write the full serial as only the first digits (excluding the last) will be accounted for. Region settings will affect the generated serial. The serial corresponds to a non-OLED/Lite console.
|
||||
**Changing serial**: Very basic way to set debug values for the serial (and battery number). Developers do not need to write the full serial as only the first digits (excluding the last) will be accoutned for. Region settings will affect the generated serial. The serial corresponds to a non-OLED/Lite console.
|
||||
|
||||
+1
-39
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this guide to get starting using the Eden emulator.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Eden-Quick-Start-2b057c2edaf6817b9859d8bcdb474017) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Eden-Quick-Start-2b057c2edaf6817b9859d8bcdb474017) for a version of this guide with images & visual elements.**
|
||||
|
||||
## Windows
|
||||
|
||||
@@ -77,41 +77,3 @@ Use this guide to get starting using the Eden emulator.
|
||||
8. Double-Click the main window to add the folder containing your games.
|
||||
9. Go to *Emulation > Configure > Input* and set up your controller. Click **OK** to close the dialog window.
|
||||
10. Double-Click a game to run it.
|
||||
|
||||
## macOS
|
||||
|
||||
Current macOS support is still experimental and very reliant on MoltenVK developments, plans have shifted to properly provide support for KosmicKrisp and similar new GPU endeavors, but macOS users still are bound to MoltenVK itself.
|
||||
|
||||
Users of macOS may wish to use [Asahi Linux](https://wiki.gentoo.org/wiki/Project:Asahi/Guide) for the rising KosmicKrisp support.
|
||||
|
||||
As of writing, neither macOS nor Asahi has support for NCE; additionally Asahi has extraneous paging bugs with fastmem.
|
||||
|
||||
### Allowing Eden to Run on MacOS
|
||||
|
||||
Use this guide when you need to allow Eden to run on a Mac system, but are being blocked by Apple Security policy.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Allowing-Eden-to-Run-on-MacOS-2b057c2edaf681fea63dc81027efeffd) for an illustrated guide.**
|
||||
|
||||
---
|
||||
|
||||
##### Pre-Requisites
|
||||
|
||||
- Permissions to modify settings in MacOS
|
||||
|
||||
---
|
||||
|
||||
#### Why am I Seeing This?
|
||||
|
||||
Recent versions of MacOS (Catalina & newer) introduced the **Gatekeeper** security functionality, requiring software to be signed by Apple or a trusted (aka - paying) developer. If the signature isn't on the list of trusted ones, it will stop the program from executing and display the message above.
|
||||
|
||||
---
|
||||
|
||||
#### Steps
|
||||
|
||||
1. Open the *System Settings* panel.
|
||||
2. Navigate to *Privacy & Security*.
|
||||
3. Scroll down and observe the following message under the **Security** settings.
|
||||
4. Select **Open Anyway** to tell your Mac that you trust the application.
|
||||
5. You will now get another window appearing to verify you want to open Eden. Select **Open Anyway**.
|
||||
6. You will be prompted for your password to authorize the request. Enter the credentials of an account that has permission to modify settings and press **OK**.
|
||||
7. Eden will now open and any subsequent launches of the program will not prompt this.
|
||||
|
||||
+3
-3
@@ -10,15 +10,13 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
|
||||
|
||||
- **[The Basics](Basics.md)**
|
||||
- **[Quickstart](./QuickStart.md)**
|
||||
- **[Windows](./QuickStart.md#windows)**
|
||||
- **[Steamdeck](./QuickStart.md#steamdeck)**
|
||||
- **[macOS](./QuickStart.md#macos)**
|
||||
- **[Settings](./Settings.md)**
|
||||
- **[Controllers](./Controllers.md)**
|
||||
- **[Controller profiles](./Controllers.md#configuring-controller-profiles)**
|
||||
- **[Audio](Audio.md)**
|
||||
- **[Graphics](Graphics.md)**
|
||||
- **[Installing Mods](./Mods.md)**
|
||||
- **[Run On macOS](./RunOnMacOS.md)**
|
||||
- **[Data, Savefiles and Storage](Storage.md)**
|
||||
- **[Orphaned Profiles](Orphaned.md)**
|
||||
- **[Troubleshooting](./Troubleshoot.md)**
|
||||
@@ -49,4 +47,6 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
|
||||
- **[Gyro Controls](./GyroControls.md)**
|
||||
- **[Platforms and Architectures](./Architectures.md)**
|
||||
- **[Native Application Development](./Native.md)**
|
||||
- **[Adding Boolean Settings Toggles](./AddingBooleanToggles.md)**
|
||||
- **[Adding Debug Knobs](./AddingDebugKnobs.md)**
|
||||
- **[Testing](./Testing.md)**
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# User Handbook - Run on macOS
|
||||
|
||||
Current macOS support is still experimental and very reliant on MoltenVK developments, plans have shifted to properly provide support for KosmicKrisp and similar new GPU endeavours, but macOS users still are bound to MoltenVK itself.
|
||||
|
||||
Users of macOS may wish to use [Asahi Linux](https://wiki.gentoo.org/wiki/Project:Asahi/Guide) for the rising KosmicKrisp support.
|
||||
|
||||
As of writing, neither macOS nor Asahi has support for NCE; additionally Asahi has extraneous paging bugs with fastmem.
|
||||
|
||||
## Allowing Eden to Run on MacOS
|
||||
|
||||
Use this guide when you need to allow Eden to run on a Mac system, but are being blocked by Apple Security policy.
|
||||
|
||||
**Click [Here](https://evilperson1337.notion.site/Allowing-Eden-to-Run-on-MacOS-2b057c2edaf681fea63dc81027efeffd) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
#### Pre-Requisites
|
||||
|
||||
- Permissions to modify settings in MacOS
|
||||
|
||||
---
|
||||
|
||||
### Why am I Seeing This?
|
||||
|
||||
Recent versions of MacOS (Catalina & newer) introduced the **Gatekeeper** security functionality, requiring software to be signed by Apple or a trusted (aka - paying) developer. If the signature isn't on the list of trusted ones, it will stop the program from executing and display the message above.
|
||||
|
||||
---
|
||||
|
||||
### Steps
|
||||
|
||||
1. Open the *System Settings* panel.
|
||||
2. Navigate to *Privacy & Security*.
|
||||
3. Scroll down and observe the following message under the **Security** settings.
|
||||
4. Select **Open Anyway** to tell your Mac that you trust the application.
|
||||
5. You will now get another window appearing to verify you want to open Eden. Select **Open Anyway**.
|
||||
6. You will be prompted for your password to authorize the request. Enter the credentials of an account that has permission to modify settings and press **OK**.
|
||||
7. Eden will now open and any subsequent launches of the program will not prompt this.
|
||||
@@ -11,7 +11,7 @@ This guide explains how to set up a public/private self hosted Eden server/lobby
|
||||
- Next, under Server OS Images, select Ubuntu 24.04 LTS. Configure CPU/RAM/specs as desired for your server. Complete the creation process.
|
||||
|
||||
- Enable the Kamatera firewall and set default policy: IN: DROP, OUT: ACCEPT.
|
||||
- After setting the default policy, add the three following rules: #1: SSH Access - Direction: IN, Interface: net0, Macro: SSH - Secure Shell Traffic, Source: ANY, Port: Blank/Auto (Handled by SSH), Destination: Blank/Auto (Handled by SSH), Policy: ACCEPT, leave a comment: SSH access.
|
||||
- After setting the default policy, add the three following rules: #1: SSH Access - Direction: IN, Interface: net0, Macro: SSH - Secure Shell Traffic, Source: ANY, Port: Blank/Auto (Handeld by SSH), Destination: Blank/Auto (Handeld by SSH), Policy: ACCEPT, leave a comment: SSH access.
|
||||
- Then, after creating the first rule, add TCP & UDP Ports for Eden - Direction: IN, Interface: net0, Protocol: TCP or UDP (for respective rule), Source: ANY, Destination Port: 24872, Policy: ACCEPT, leave a comment: Eden server port.
|
||||
- Note: Only UDP is required for Eden; opening TCP is optional.
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ Most of the development adds new settings that enhance performance/compatibility
|
||||
|
||||
As such, this guide will NOT mention those kind of settings, we'd rather mention settings which have a long shelf time (i.e won't get removed in future releases) and are likely to be unchanged.
|
||||
|
||||
Some of the options are self explanatory, and they do exactly what they say they do (i.e "Pause when not in focus"); such options will be also skipped due to triviality.
|
||||
Some of the options are self explainatory, and they do exactly what they say they do (i.e "Pause when not in focus"); such options will be also skipped due to triviality.
|
||||
|
||||
## Foreword
|
||||
|
||||
Before touching the settings, see the game boots with stock options. We try our best to ensure users can boot any game using the default settings. If they don't work, then you may try fiddling with options - but please, first use stock options.
|
||||
Before touching the settings, please see the game boots with stock options. We try our best to ensure users can boot any game using the default settings. If they don't work, then you may try fiddling with options - but please, first use stock options.
|
||||
|
||||
## General
|
||||
|
||||
@@ -25,15 +25,15 @@ Before touching the settings, see the game boots with stock options. We try our
|
||||
|
||||
## System
|
||||
|
||||
- `System/RNG Seed`: Set to 0 (and uncheck) to disable ASLR system-wide (this makes mods like CTGP to stop working); by default it enables ASLR to replicate console behavior.
|
||||
- `System/RNG Seed`: Set to 0 (and uncheck) to disable ASLR systemwide (this makes mods like CTGP to stop working); by default it enables ASLR to replicate console behaviour.
|
||||
- `Network/Enable Airplane Mode`: Enable this if a game is crashing before loading AND the logs mention anything related to "web" or "internet" services.
|
||||
|
||||
## CPU
|
||||
|
||||
- `Fastmem`, aka. `CPU/Enable Host MMU`: Enables "fastmem"; a detailed description of fastmem can be found [here](../dynarmic/Design.md#fast-memory-fastmem).
|
||||
- `CPU/Unsafe FMA`: Enables deliberate inaccurate FMA behavior which may affect how FMA returns any given operation - this may introduce tiny floating point errors which can cascade in sensitive code (i.e FFmpeg).
|
||||
- `CPU/Unsafe FMA`: Enables deliberate innacurate FMA behaviour which may affect how FMA returns any given operation - this may introduce tiny floating point errors which can cascade in sensitive code (i.e FFmpeg).
|
||||
- `CPU/Faster FRSQRTE and FRECPE`: Introduces accuracy errors on square root and reciprocals in exchange for less checks - this introduces inaccuracies with some cases but it's mostly safe.
|
||||
- `CPU/Faster ASIMD Instructions`: Skips rounding mode checks for ARM ASIMD instructions - this means some code depending on these rounding modes may misbehave.
|
||||
- `CPU/Faster ASIMD Instructions`: Skips rounding mode checks for ARM ASIMD instructions - this means some code dpeending on these rounding modes may misbehave.
|
||||
- `CPU/Disable address space checks`: Before each memory access, the emulator checks the address is in range, if not it faults; this option makes it so the emulator skips the check entirely (which may be expensive for a myriad of reasons). However at the same time this allows the guest program to "break out" of the emulation context by writing to arbitrary addresses.
|
||||
- `CPU/Ignore global monitor`: This relies on a quirk present on x86 to avoid the ARM global monitor emulation, this may increase performance in mutex-heavy contexts (i.e games waiting for next frames or such); but also can cause deadlocks and fun to debug issues.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Use this when you want to import the Eden AppImage into your Steam Library along with artwork using *Steam ROM Manager.*
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Importing-Eden-into-Steam-with-Steam-Rom-Manager-2b757c2edaf68054851bc287b6382cb5) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Importing-Eden-into-Steam-with-Steam-Rom-Manager-2b757c2edaf68054851bc287b6382cb5) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
@@ -114,7 +114,7 @@ We will need to create a new parser for the Emulators. Unlike with the EmuDeck
|
||||
2. **Parser Title**: *Emulators - Emulators*
|
||||
3. **Steam Directory**: *${steamdirglobal}*
|
||||
4. **User Accounts**: *Global*
|
||||
5. **ROMs Directory**: <path to directory containing Eden AppImage>
|
||||
5. **ROMs Directory**: <path to directory containing eden AppImage>
|
||||
6. **Steam Collections**: *Emulation* (OPTIONAL)
|
||||
2. Parser Specific Configuration
|
||||
1. **Search Glob**: *${title}@(.AppImage|.APPIMAGE|.appimage)*
|
||||
@@ -167,7 +167,7 @@ Now that we have the parser or shell script created, we can actually add it to S
|
||||
|
||||
Use this when you want to import your games inside Eden into Steam to launch with artwork from Steam Game Mode without needing to launch Eden first.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Importing-Games-into-Steam-with-Steam-Rom-Manager-2b757c2edaf680d7a491c92b138f1fcc) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Importing-Games-into-Steam-with-Steam-Rom-Manager-2b757c2edaf680d7a491c92b138f1fcc) for a version of this guide with images & visual elements.**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this guide for when you want to configure automated backup/syncing of your Eden save files using [*Syncthing*](https://syncthing.net/).
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Backing-Up-Syncing-Eden-Game-Saves-2b357c2edaf68000b40cfab2c2c3dc0a) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Backing-Up-Syncing-Eden-Game-Saves-2b357c2edaf68000b40cfab2c2c3dc0a) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Pre-Requisites
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ For regressions/bugs from PRs or commits:
|
||||
- [ ] Bisected PR? (if it has commits)
|
||||
- [ ] Found bisected commit?
|
||||
|
||||
If an issue sporadically appears, try to do multiple runs, try if possible, to count the number of times it has failed and the number of times it has "worked just fine"; say it worked 3 times but failed 1. then there is a 1/4th chance every run that the issue is replicated - so every bisect step would require 4 runs to ensure there is at least a chance of triggering the bug.
|
||||
If an issue sporadically appears, try to do multiple runs, try if possible, to count the number of times it has failed and the number of times it has "worked just fine"; say it worked 3 times but failed 1. then there is a 1/4th chance every run that the issue is replicated - so every bisect step would require 4 runs to ensure there is atleast a chance of triggering the bug.
|
||||
|
||||
## What to do when something seems off
|
||||
|
||||
@@ -96,4 +96,4 @@ The faulty commit then, is 6th of Jan. This is called bisection https://git-scm.
|
||||
- PR's marked with **WIP** do NOT need to be tested unless explicitly asked (check the git in case)
|
||||
- Sometimes license checks may fail, hover over the build icon to see if builds did succeed, as the CI will push builds even if license checks fail.
|
||||
- All open PRs can be viewed [here](https://git.eden-emu.dev/eden-emu/eden/pulls/).
|
||||
- If site is down use one of the [mirrors](./ThirdParty.md#mirrors).
|
||||
- If site is down use one of the [mirrors](./user/ThirdParty.md#mirrors).
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# User Handbook - Third party tools and extras
|
||||
|
||||
The Eden emulator by itself lacks some functionality - or otherwise requires external files (such as packaging) to operate correctly in a given OS. Addendum to that some repositories provide nightly or specialized builds of the emulator.
|
||||
The Eden emulator by itself lacks some functionality - or otherwise requires external files (such as packaging) to operate correctly in a given OS. Addendum to that some repositories provide nightly or specialised builds of the emulator.
|
||||
|
||||
While most of the links mentioned in this guide are relatively "safe"; we urge users to use their due diligence and appropriately verify the integrity of all files downloaded and ensure they're not compromised.
|
||||
While most of the links mentioned in this guide are relatively "safe"; we urge users to use their due diligence and appropriatedly verify the integrity of all files downloaded and ensure they're not compromised.
|
||||
|
||||
- [NixOS Eden Flake](https://github.com/Grantimatter/eden-flake)
|
||||
- [ES-DE Frontend Support](https://github.com/GlazedBelmont/es-de-android-custom-systems)
|
||||
@@ -18,13 +18,13 @@ The main origin repository is always at <https://git.eden-emu.dev/eden-emu/eden>
|
||||
|
||||
Other mirrors obviously exist on the internet, but we can't guarantee their reliability and/or availability.
|
||||
|
||||
If you're someone wanting to make a mirror, simply setup Forgejo and automatically mirror from the origin repository. Or you could mirror a mirror to save us bandwidth... your choice!
|
||||
If you're someone wanting to make a mirror, simply setup forgejo and automatically mirror from the origin repository. Or you could mirror a mirror to save us bandwidth... your choice!
|
||||
|
||||
## Configuring Obtainium
|
||||
|
||||
Very nice handy app, here's a quick rundown how to configure:
|
||||
|
||||
1. Copy the URL: <https://git.eden-emu.dev/eden-emu/eden/> (or one of your favorite mirrors)
|
||||
1. Copy the URL: <https://git.eden-emu.dev/eden-emu/eden/> (or one of your favourite mirrors)
|
||||
2. Open Obtainium and tap `Add App`.
|
||||
3. Paste the URL into the `App Source URL` field.
|
||||
4. Override Source: Look for the `Override Source` dropdown menu and select `Forgejo (Codeberg)`.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
## Eden Fails to Launch and Does Not Leave Any Logs
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Windows-Eden-Fails-to-Launch-and-Does-Not-Leave-Any-Logs-2b057c2edaf68156b640cf1ac549870a) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Windows-Eden-Fails-to-Launch-and-Does-Not-Leave-Any-Logs-2b057c2edaf68156b640cf1ac549870a) for a version of this guide with images & visual elements.**
|
||||
|
||||
### Error Details
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
**Error Log Entries:**
|
||||
|
||||
```text
|
||||
```
|
||||
None
|
||||
```
|
||||
**Example Error Message Entry in Windows Event Viewer**
|
||||
```text
|
||||
```
|
||||
Faulting application name: eden.exe, version: 0.0.0.0, time stamp: 0x6795dc3c
|
||||
Faulting module name: ntdll.dll, version: 10.0.26100.3037, time stamp: 0x95e6c489
|
||||
Exception code: 0xc0000005
|
||||
@@ -73,7 +73,7 @@ Faulting package-relative application ID:
|
||||
|
||||
5. Look for an entry with the Level of Error, and look for a message similar to the following
|
||||
|
||||
```text
|
||||
```
|
||||
Faulting application name: Eden.exe, version: 0.0.0.0, time stamp: 0x6795dc3c
|
||||
Faulting module name: ntdll.dll, version: 10.0.26100.3037, time stamp: 0x95e6c489
|
||||
Exception code: 0xc0000005
|
||||
@@ -90,7 +90,7 @@ Faulting package-relative application ID:
|
||||
6. Run a Command Prompt terminal Window as Administrator.
|
||||
7. Enter the following command and wait for it to complete. It will take a while, just be patient and do other things while it completes.
|
||||
|
||||
```bat
|
||||
```
|
||||
DISM /Online /Cleanup-Image /RestoreHealth
|
||||
```
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this guide when you want to load Amiibo into your games for use with the Eden emulator.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Using-Amiibo-with-Eden-2b057c2edaf681b1b28ec6be600c6d3e) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Using-Amiibo-with-Eden-2b057c2edaf681b1b28ec6be600c6d3e) for a version of this guide with images & visual elements.**
|
||||
|
||||
## Android
|
||||
|
||||
@@ -17,7 +17,7 @@ TBD
|
||||
|
||||
<aside>
|
||||
|
||||
***NOTE***: Eden only supports the *.bin* Amiibo format, ***NOT*** the *.nfc* format.
|
||||
***NOTE***: Eden only supports the *.bin* amiibo format, ***NOT*** the *.nfc* format.
|
||||
|
||||
</aside>
|
||||
|
||||
@@ -37,7 +37,7 @@ TBD
|
||||
|
||||
<aside>
|
||||
|
||||
***NOTE***: It seems the scanning functionality is spotty and will sometimes throw a "*The current game is not looking for Amiibos*" message, even though it is. Usually you just need to try loading it again or restarting the scanning from the game. In some situations it was only resolved by restarting the game.
|
||||
***NOTE***: It seems the scanning functionality is spotty and will sometimes throw a "*The current game is not looking for amiibos*" message, even though it is. Usually you just need to try loading it again or restarting the scanning from the game. In some situations it was only resolved by restarting the game.
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Use this guide when you want to add cheats into a game to alter gameplay for use with the Eden emulator.
|
||||
|
||||
**[See here](https://evilperson1337.notion.site/Using-Cheats-with-Eden-2b057c2edaf6818fab66c276e2304bb4) for an illustrated guide.**
|
||||
**Click [Here](https://evilperson1337.notion.site/Using-Cheats-with-Eden-2b057c2edaf6818fab66c276e2304bb4) for a version of this guide with images & visual elements.**
|
||||
|
||||
## Android
|
||||
|
||||
|
||||
Vendored
+5
@@ -254,6 +254,11 @@ endif()
|
||||
# TZDB (Time Zone Database)
|
||||
add_subdirectory(nx_tzdb)
|
||||
|
||||
# PowerPC emitter
|
||||
if (ARCHITECTURE_powerpc64)
|
||||
add_subdirectory(powah)
|
||||
endif()
|
||||
|
||||
add_library(tz tz/tz/tz.cpp)
|
||||
target_include_directories(tz PUBLIC ./tz)
|
||||
|
||||
|
||||
+2
-2
@@ -166,7 +166,7 @@ detect_architecture_symbols(
|
||||
"_M_MRX000")
|
||||
|
||||
detect_architecture_symbols(
|
||||
ARCH ppc64
|
||||
ARCH powerpc64
|
||||
SYMBOLS
|
||||
"__ppc64__"
|
||||
"__powerpc64__"
|
||||
@@ -174,7 +174,7 @@ detect_architecture_symbols(
|
||||
"_M_PPC64")
|
||||
|
||||
detect_architecture_symbols(
|
||||
ARCH ppc
|
||||
ARCH powerpc
|
||||
SYMBOLS
|
||||
"__ppc__"
|
||||
"__ppc"
|
||||
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
add_library(powah INTERFACE)
|
||||
target_include_directories(powah INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_options(powah INTERFACE -Wno-unused-parameter)
|
||||
|
||||
add_executable(powah_tests tests.cpp)
|
||||
create_target_directory_groups(powah_tests)
|
||||
target_link_libraries(powah_tests PRIVATE Catch2::Catch2WithMain)
|
||||
Vendored
+145
@@ -0,0 +1,145 @@
|
||||
vabsdub,VX,04,1027
|
||||
vabsduh,VX,04,1091
|
||||
vabsduw,VX,04,1155
|
||||
vaddcuw,VX,04,384
|
||||
vaddfp,VX,04,10
|
||||
vaddsbs,VX,04,768
|
||||
vaddshs,VX,04,832
|
||||
vaddsws,VX,04,896
|
||||
vaddubm,VX,04,0
|
||||
vaddubs,VX,04,512
|
||||
vadduhm,VX,04,64
|
||||
vadduhs,VX,04,576
|
||||
vadduwm,VX,04,128
|
||||
vadduws,VX,04,640
|
||||
vand,VX,04,1028
|
||||
vandc,VX,04,1092
|
||||
vavgsb,VX,04,1282
|
||||
vavgsh,VX,04,1346
|
||||
vavgsw,VX,04,1410
|
||||
vavgub,VX,04,1026
|
||||
vavguh,VX,04,1090
|
||||
vavguw,VX,04,1154
|
||||
vcfsx,VDU,04842
|
||||
vcfux,VDU,04778
|
||||
vcmpbfp,VXR,04,966
|
||||
vcmpeqfp,VXR,04,198
|
||||
vcmpequb,VXR,04,6
|
||||
vcmpequh,VXR,04,70
|
||||
vcmpequw,VXR,04,134
|
||||
vcmpgefp,VXR,04,454
|
||||
vcmpgtfp,VXR,04,710
|
||||
vcmpgtsb,VXR,04,774
|
||||
vcmpgtsh,VXR,04,838
|
||||
vcmpgtsw,VXR,04,902
|
||||
vcmpgtub,VXR,04,518
|
||||
vcmpgtuh,VXR,04,582
|
||||
vcmpgtuw,VXR,04,646
|
||||
vctsxs,VDU,04970
|
||||
vctuxs,VDU,04906
|
||||
vexptefp,VY,04,394
|
||||
vlogefp,VY,04,458
|
||||
vmaddfp,VXC,46
|
||||
vmaxfp,VX,04,1034
|
||||
vmaxsb,VX,04,258
|
||||
vmaxsh,VX,04,322
|
||||
vmaxsw,VX,04,386
|
||||
vmaxub,VX,04,2
|
||||
vmaxuh,VX,04,66
|
||||
vmaxuw,VX,04,130
|
||||
vmhaddshs,VXC,32
|
||||
vmhraddshs,VXC,33
|
||||
vminfp,VX,04,1098
|
||||
vminsb,VX,04,770
|
||||
vminsh,VX,04,834
|
||||
vminsw,VX,04,898
|
||||
vminub,VX,04,514
|
||||
vminuh,VX,04,578
|
||||
vminuw,VX,04,642
|
||||
vmladduhm,VXC,34
|
||||
vmrghb,VX,04,12
|
||||
vmrghh,VX,04,76
|
||||
vmrghw,VX,04,140
|
||||
vmrglb,VX,04,268
|
||||
vmrglh,VX,04,332
|
||||
vmrglw,VX,04,396
|
||||
vmsummbm,VXC,37
|
||||
vmsumshm,VXC,40
|
||||
vmsumshs,VXC,41
|
||||
vmsumubm,VXC,36
|
||||
vmsumuhm,VXC,38
|
||||
vmsumuhs,VXC,39
|
||||
vmulesb,VX,04,776
|
||||
vmulesh,VX,04,840
|
||||
vmuleub,VX,04,520
|
||||
vmuleuh,VX,04,584
|
||||
vmulosb,VX,04,264
|
||||
vmulosh,VX,04,328
|
||||
vmuloub,VX,04,8
|
||||
vmulouh,VX,04,72
|
||||
vnmsubfp,VXC,47
|
||||
vnor,VX,04,1284
|
||||
vor,VX,04,1156
|
||||
vperm,VXC,43
|
||||
vpkpx,VX,04,782
|
||||
vpkshss,VX,04,398
|
||||
vpkshus,VX,04,270
|
||||
vpkswss,VX,04,462
|
||||
vpkswus,VX,04,334
|
||||
vpkuhum,VX,04,14
|
||||
vpkuhus,VX,04,142
|
||||
vpkuwum,VX,04,78
|
||||
vpkuwus,VX,04,206
|
||||
vrefp,VY,04,266
|
||||
vrfim,VY,04,714
|
||||
vrfin,VY,04,522
|
||||
vrfip,VY,04,650
|
||||
vrfiz,VY,04,586
|
||||
vrlb,VX,04,4
|
||||
vrlh,VX,04,68
|
||||
vrlw,VX,04,132
|
||||
vrsqrtefp,VY,04,330
|
||||
vsel,VXC,42
|
||||
vsl,VX,04,452
|
||||
vslb,VX,04,260
|
||||
vsldoi,VX,04,/ SH 44
|
||||
vslh,VX,04,324
|
||||
vslo,VX,04,1036
|
||||
vslw,VX,04,388
|
||||
vspltb,VU,04,524
|
||||
vsplth,VU,04,588
|
||||
vspltisb,VS,04,780
|
||||
vspltish,VS,04,844
|
||||
vspltisw,VS,04,908
|
||||
vspltw,VSU,04,652
|
||||
vsr,VX,04,708
|
||||
vsrab,VX,04,772
|
||||
vsrah,VX,04,836
|
||||
vsraw,VX,04,900
|
||||
vsrb,VX,04,516
|
||||
vsrh,VX,04,580
|
||||
vsro,VX,04,1100
|
||||
vsrw,VX,04,644
|
||||
vsubcuw,VX,04,1408
|
||||
vsubfp,VX,04,74
|
||||
vsubsbs,VX,04,1792
|
||||
vsubshs,VX,04,1856
|
||||
vsubsws,VX,04,1920
|
||||
vsububm,VX,04,1024
|
||||
vsububs,VX,04,1536
|
||||
vsubuhm,VX,04,1088
|
||||
vsubuhs,VX,04,1600
|
||||
vsubuwm,VX,04,1152
|
||||
vsubuws,VX,04,1664
|
||||
vsumsws,VX,04,1928
|
||||
vsum2sws,VX,04,1672
|
||||
vsum4sbs,VX,04,1800
|
||||
vsum4shs,VX,04,1608
|
||||
vsum4ubs,VX,04,1544
|
||||
vupkhpx,VY,04,846
|
||||
vupkhsb,VY,04,526
|
||||
vupkhsh,VY,04,590
|
||||
vupklpx,VY,04,974
|
||||
vupklsb,VY,04,654
|
||||
vupklsh,VY,04,718
|
||||
vxor,VX,04,122
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
$CC data2code.c -o data2code && ./data2code data.txt >powah_gen_base.hpp
|
||||
$CC --target=powerpc64le test.S -c -o test && objdump -SC test
|
||||
Vendored
+222
@@ -0,0 +1,222 @@
|
||||
add[o][.],Add,XO,31,266
|
||||
addc[o][.],Add Carrying,XO,31,10
|
||||
adde[o][.],Add Extended,XO,31,138
|
||||
addi,Add Immediate,D,14,
|
||||
addic,Add Immediate Carrying,D,12,
|
||||
addic.,Add Immediate Carrying and Record,D,13,
|
||||
addis,Add Immediate Shifted,D,15,
|
||||
addme[o][.],Add to Minus One Extended,XO,31,234
|
||||
addze[o][.],Add to Zero Extended,XO,31,202
|
||||
and[.],AND,X,31,28
|
||||
andc[.],AND with Complement,X,31,60
|
||||
andi.,AND Immediate,D,28,
|
||||
andis.,AND Immediate Shifted,D,29,
|
||||
b[l][a],Branch,I,18,
|
||||
bc[l][a],Branch Conditional,B,16,
|
||||
bcctr[l],Branch Conditional to Count Register,XL,19,528
|
||||
bclr[l],Branch Conditional Link Register,XL,19,16
|
||||
cmp,Compare,X,31,0
|
||||
cmpi,Compare Immediate,D,11,
|
||||
cmpl,Compare Logical,X,31,32
|
||||
cmpli,Compare Logical Immediate,D,10,
|
||||
cntlzd,Count Leading Zeros Doubleword,X,31,58
|
||||
cntlzw[.],Count Leading Zeros Word,X,31,26
|
||||
crand,Condition Register AND,XL,19,257
|
||||
crandc,Condition Register AND with Complement,XL,19,129
|
||||
creqv,Condition Register Equivalent,XL,19,289
|
||||
crnand,Condition Register NAND,XL,19,225
|
||||
crnor,Condition Register NOR,XL,19,33
|
||||
cror,Condition Register OR,XL,19,449
|
||||
crorc,Condition Register OR with Complement,XL,19,417
|
||||
crxor,Condition Register XOR,XL,19,193
|
||||
dcbf,Data Cache Block Flush,X,31,86
|
||||
dcbi,Data Cache Block Invalidate,X,31,470
|
||||
dcbst,Data Cache Block Store,X,31,54
|
||||
dcbt,Data Cache Block Touch,X,31,278
|
||||
dcbtst,Data Cache Block Touch for Store,X,31,246
|
||||
dcbz,Data Cache Block Set to Zero,X,31,1014
|
||||
divd,Divide Doubleword,XO,31,489
|
||||
divdu,Divide Doubleword Unsigned,XO,31,457
|
||||
divw[o][.],Divide Word,XO,31,491
|
||||
divwu[o][.],Divide Word Unsigned,XO,31,459
|
||||
eciwx,External Control in Word Indexed (opt.),X,31,310
|
||||
ecowx,External Control out Word Indexed (opt.),X,31,438
|
||||
eieio,Enforce In-order Execution of I/O,X,31,854
|
||||
eqv[.],Equivalent,X,31,284
|
||||
extsb[.],Extend Sign Byte,X,31,954
|
||||
extsh[.],Extend Sign Halfword,XO,31,922
|
||||
extsw,Extend Sign Word,X,31,986
|
||||
fabs[.],Floating Absolute Value,X,63,264
|
||||
fadd[.],Floating Add,A,63,21
|
||||
fadds[.],Floating Add Single,A,59,21
|
||||
fcfid,Floating Convert from Integer Doubleword,X,63,846
|
||||
fcmpo,Floating Compare Ordered,X,63,32
|
||||
fcmpu,Floating Compare Unordered,XL,63,0
|
||||
fctid,Floating Convert to Integer Doubleword,X,63,814
|
||||
fctidz,Floating Convert to Integer Doubleword with Round Toward Zero,X,63,815
|
||||
fctiw[.],Floating Convert to Integer Word,X,63,14
|
||||
fctiwz[.],Floating Convert to Integer Word with Round to Zero,XL,63,15
|
||||
fdiv[.],Floating Divide,A,63,18
|
||||
fdivs[.],Floating Divide Single,A,59,18
|
||||
fmadd[.],Floating Multiply-Add,A,63,29
|
||||
fmadds[.],Floating Multiply-Add Single,A,59,29
|
||||
fmr[.],Floating Move Register,X,63,72
|
||||
fmsub[.],Floating Multiply-Subtract,A,63,28
|
||||
fmsubs[.],Floating Multiply-Subtract Single,A,59,28
|
||||
fmul[.],Floating Multiply,A,63,25
|
||||
fmuls[.],Floating Multiply Single,A,59,25
|
||||
fnabs[.],Floating Negative Absolute Value,X,63,136
|
||||
fneg[.],Floating Negate,X,63,40
|
||||
fnmadd[.],Floating Negative Multiply-Add,A,63,31
|
||||
fnmadds[.],Floating Negative Multiply-Add Single,A,59,31
|
||||
fnmsub[.],Floating Negative Multiply-Subtract,A,63,30
|
||||
fnmsubs[.],Floating Negative Multiply-Subtract Single,A,59,30
|
||||
fres[.],Floating Reciprocal Estimate Single (optional),A,59,24
|
||||
frsp[.],Floating Round to Single Precision,X,63,12
|
||||
frsqrte[.],Floating Reciprocal Square Root Estimate (optional),A,63,26
|
||||
fsel[.],Floating-Point Select (optional),A,63,23
|
||||
fsub[.],Floating Subtract,A,63,20
|
||||
fsubs[.],Floating Subtract Single,A,59,20
|
||||
icbi,Instruction Cache Block Invalidate,X,31,982
|
||||
isync,Instruction Synchronize,X,19,150
|
||||
lbz,Load Byte and Zero,D,34,
|
||||
lbzu,Load Byte and Zero with Update,D,35,
|
||||
lbzux,Load Byte and Zero with Update Indexed,X,31,119
|
||||
lbzx,Load Byte and Zero Indexed,X,31,87
|
||||
ld,Load Doubleword,DS,58,0
|
||||
ldarx,Load Doubleword and Reserve Indexed,X,31,84
|
||||
ldu,Load Doubleword with Update,DS,58,1
|
||||
ldux,Load Doubleword with Update Indexed,X,31,53
|
||||
ldx,Load Doubleword Indexed,X,31,21
|
||||
lfd,Load Floating-Point Double,D,50,
|
||||
lfdu,Load Floating-Point Double with Update,D,51,
|
||||
lfdux,Load Floating-Point Double with Update Indexed,X,31,631
|
||||
lfdx,Load Floating-Point Double Indexed,X,31,599
|
||||
lfs,Load Floating-Point Single,D,48,
|
||||
lfsu,Load Floating-Point Single with Update,D,49,
|
||||
lfsux,Load Floating-Point Single with Update Indexed,X,31,567
|
||||
lfsx,Load Floating-Point Single Indexed,X,31,535
|
||||
lha,Load Half Algebraic,D,42,
|
||||
lhau,Load Half Algebraic with Update,D,43,
|
||||
lhaux,Load Half Algebraic with Update Indexed,X,31,375
|
||||
lhax,Load Half Algebraic Indexed,X,31,343
|
||||
lhbrx,Load Half Byte-Reversed Indexed,X,31,790
|
||||
lhz,Load Half and Zero,D,40,
|
||||
lhzu,Load Half and Zero with Update,D,41,
|
||||
lhzux,Load Half and Zero with Update Indexed,X,31,331
|
||||
lhzx,Load Half and Zero Indexed,X,31,279
|
||||
lmw,Load Multiple Word,D,46,
|
||||
lswi,Load String Word Immediate,X,31,597
|
||||
lswx,Load String Word Indexed,X,31,533
|
||||
lwa,Load Word Algebraic,DS,58,2
|
||||
lwarx,Load Word and Reserve Indexed,X,31,20
|
||||
lwaux,Load Word Algebraic with Update Indexed,X,31,373
|
||||
lwax,Load Word Algebraic Indexed,X,31,341
|
||||
lwbrx,Load Word Byte-Reversed Indexed,X,31,534
|
||||
lwz,Load Word and Zero,D,32,
|
||||
lwzu,Load Word with Zero Update,D,33,
|
||||
lwzux,Load Word and Zero with Update Indexed,X,31,55
|
||||
lwzx,Load Word and Zero Indexed,X,31,23
|
||||
mcrf,Move Condition Register Field,XL,19,0
|
||||
mcrfs,Move to Condition Register from FPSCR,X,63,64
|
||||
mcrxr,Move to Condition Register from XER,X,31,512
|
||||
mfcr,Move from Condition Register,X,31,19
|
||||
mffs[.],Move from FPSCR,X,63,583
|
||||
mfmsr,Move from Machine State Register,X,31,83
|
||||
mfspr,Move from Special-Purpose Register,X,31,339
|
||||
mfsr,Move from Segment Register,X,31,595
|
||||
mfsrin,Move from Segment Register Indirect,X,31,659
|
||||
mtcrf,Move to Condition Register Fields,XFX,31,144
|
||||
mtfsb0[.],Move to FPSCR Bit 0,X,63,70
|
||||
mtfsb1[.],Move to FPSCR Bit 1,X,63,38
|
||||
mtfsf[.],Move to FPSCR Fields,XFL,63,711
|
||||
mtfsfi[.],Move to FPSCR Field Immediate,X,63,134
|
||||
mtmsr,Move to Machine State Register,X,31,146
|
||||
mtspr,Move to Special-Purpose Register,X,31,467
|
||||
mtsr,Move to Segment Register,X,31,210
|
||||
mtsrin,Move to Segment Register Indirect,X,31,242
|
||||
mulhd,Multiply High Doubleword,XO,31,73
|
||||
mulhdu,Multiply High Doubleword Unsigned,XO,31,9
|
||||
mulhw[.],Multiply High Word,XO,31,75
|
||||
mulhwu[.],Multiply High Word Unsigned,XO,31,11
|
||||
mulld,Multiply Low Doubleword,XO,31,233
|
||||
mulli,Multiply Low Immediate,D,07,
|
||||
mullw[o][.],Multiply Low Word,XO,31,235
|
||||
nand[.],NAND,X,31,476
|
||||
neg[o][.],Negate,XO,31,104
|
||||
nor[.],NOR,X,31,124
|
||||
or[.],OR,X,31,444
|
||||
orc[.],OR with Complement,X,31,412
|
||||
ori,OR Immediate,D,24,
|
||||
oris,OR Immediate Shifted,D,25,
|
||||
rfi,Return from Interrupt,X,19,50
|
||||
rldcl,Rotate Left Doubleword then Clear Left,MDS,30,8
|
||||
rldcr,Rotate Left Doubleword then Clear Right,MDS,30,9
|
||||
rldic,Rotate Left Doubleword Immediate then Clear,MD,30,2
|
||||
rldicl,Rotate Left Doubleword Immediate then Clear Left,MD,30,0
|
||||
rldicr,Rotate Left Doubleword Immediate then Clear Right,MD,30,1
|
||||
rldimi,Rotate Left Doubleword Immediate then Mask Insert,MD,30,3
|
||||
rlwimi[.],Rotate Left Word Immediate then Mask Insert,M,20,
|
||||
rlwinm[.],Rotate Left Word Immediate then AND with Mask,M,21,
|
||||
rlwnm[.],Rotate Left Word then AND with Mask,M,23,
|
||||
sc,System Call,SC,17,
|
||||
si,Subtract Immediate,D,12,
|
||||
si.,Subtract Immediate and Record,D,13,
|
||||
slbia,SLB Invalidate All,X,31,498
|
||||
slbie,SLB Invalidate Entry,X,31,434
|
||||
sld,Shift Left Doubleword,X,31,27
|
||||
slw[.],Shift Left Word,X,31,24
|
||||
srad,Shift Right Algebraic Doubleword,X,31,794
|
||||
sradi,Shift Right Algebraic Doubleword Immediate,XS,31,413
|
||||
srd,Shift Right Doubleword,X,31,539
|
||||
sraw[.],Shift Right Algebraic Word,X,31,792
|
||||
srawi[.],Shift Right Algebraic Word Immediate,X,31,824
|
||||
srw[.],Shift Right Word,X,31,536
|
||||
stb,Store Byte,D,38,
|
||||
stbu,Store Byte with Update,D,39,
|
||||
stbux,Store Byte with Update Indexed,X,31,247
|
||||
stbx,Store Byte Indexed,X,31,215
|
||||
std,Store Doubleword,DS,62,0
|
||||
stdcx,Store Doubleword Conditional Indexed,X,31,214
|
||||
stdu,Store Doubleword with Update,DS,62,1
|
||||
stdux,Store Doubleword with Update Indexed,X,31,181
|
||||
stdx,Store Doubleword Indexed,X,31,149
|
||||
stfd,Store Floating-Point Double,D,54,
|
||||
stfdu,Store Floating-Point Double with Update,D,55,
|
||||
stfdux,Store Floating-Point Double with Update Indexed,X,31,759
|
||||
stfdx,Store Floating-Point Double Indexed,X,31,727
|
||||
stfiwx,Store Floating-Point as Integer Word Indexed (optional),X,31,983
|
||||
stfs,Store Floating-Point Single,D,52,
|
||||
stfsu,Store Floating-Point Single with Update,D,53,
|
||||
stfsux,Store Floating-Point Single with Update Indexed,X,31,695
|
||||
stfsx,Store Floating-Point Single Indexed,X,31,663
|
||||
sth,Store Half,D,44,
|
||||
sthbrx,Store Half Byte-Reverse Indexed,X,31,918
|
||||
sthu,Store Half with Update,D,45,
|
||||
sthux,Store Half with Update Indexed,X,31,439
|
||||
sthx,Store Half Indexed,X,31,407
|
||||
stmw,Store Multiple Word,D,47,
|
||||
stswi,Store String Word Immediate,X,31,725
|
||||
stswx,Store String Word Indexed,X,31,661
|
||||
stw,Store,D,36,
|
||||
stwbrx,Store Word Byte-Reversed Indexed,X,31,662
|
||||
stwcx.,Store Word Conditional Indexed,X,31,150
|
||||
stwu,Store Word with Update,D,37,
|
||||
stwux,Store Word with Update Indexed,X,31,183
|
||||
stwx,Store Word Indexed,X,31,151
|
||||
subf[o][.],Subtract from,XO,31,40
|
||||
subfc[o][.],Subtract from Carrying,XO,31,08
|
||||
subfe[o][.],Subtract from Extended,XO,31,136
|
||||
subfic,Subtract from Immediate Carrying,D,08,
|
||||
subfme[o][.],Subtract from Minus One Extended,XO,31,232
|
||||
subfze[o][.],Subtract from Zero Extended,XO,31,200
|
||||
sync,Synchronize,X,31,598
|
||||
td,Trap Doubleword,X,31,68
|
||||
tdi,Trap Doubleword Immediate,D,2,
|
||||
tlbie,Translation Look-aside Buffer Invalidate Entry (optional),X,31,306
|
||||
tlbsync,Translation Look-aside Buffer Synchronize (optional),X,31,566
|
||||
tw,Trap Word,X,31,04
|
||||
twi,Trap Word Immediate,D,03,
|
||||
xor[.],XOR,X,31,316
|
||||
xori,XOR Immediate,D,26,
|
||||
xoris,XOR Immediate Shift,D,27,
|
||||
Vendored
+340
@@ -0,0 +1,340 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
int main(int argc, char *argv[]) {
|
||||
printf(
|
||||
"// this file is autogenerated DO NOT MODIFY\n"
|
||||
"#pragma once\n"
|
||||
);
|
||||
FILE* fp = fopen(argv[1], "rt");
|
||||
if (fp) {
|
||||
char line[80];
|
||||
while (fgets(line, sizeof line, fp) != NULL) {
|
||||
bool with_o = strstr(line, "[o]"), with_d = strstr(line, "[.]");
|
||||
char* p = strchr(line, '\n'), *name = strchr(line, ','), *mem = line;
|
||||
if (p) *p = '\0';
|
||||
if (name) {
|
||||
*name++ = '\0';
|
||||
char *form = strchr(name, ',');
|
||||
if (form) {
|
||||
*form++ = '\0';
|
||||
char *opc = strchr(form, ',');
|
||||
if (opc) {
|
||||
*opc++ = '\0';
|
||||
char *sec = strchr(opc, ',');
|
||||
if (sec) {
|
||||
struct b_info { const char *s; int o; int p; } infos[] = {
|
||||
{"",1,0},
|
||||
{"LT",1,12},
|
||||
{"LE",2,4},
|
||||
{"NG",2,4},
|
||||
{"EQ",3,12},
|
||||
{"GE",1,4},
|
||||
{"NL",1,4},
|
||||
{"GT",2,12},
|
||||
{"NE",3,4},
|
||||
{"SO",4,12},
|
||||
{"UN",4,12},
|
||||
{"NS",4,4},
|
||||
{"NU",4,4},
|
||||
};
|
||||
#define OP_EXT ((i_opcode << 26) | (i_extopc << 1))
|
||||
if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0';
|
||||
if (strchr(mem, '.') != NULL) *strchr(mem, '.') = '_';
|
||||
*sec++ = '\0';
|
||||
for (int i = 0; i < strlen(mem); ++i)
|
||||
mem[i] = toupper(mem[i]);
|
||||
int i_opcode = atoi(opc);
|
||||
int i_extopc = atoi(sec);
|
||||
//printf("// %s\n", mem);
|
||||
if (!strcmp(form, "XO")) {
|
||||
if (!strcmp(mem, "EXTSH")) {
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra) {"
|
||||
" emit_%s(0x%08x, rt, ra, R0, false, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sC(GPR const rt, GPR const ra) {"
|
||||
" emit_%s(0x%08x, rt, ra, R0, true, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(GPR const rt, GPR const ra) {"
|
||||
" emit_%s(0x%08x, rt, ra, R0, false, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sC_(GPR const rt, GPR const ra) {"
|
||||
" emit_%s(0x%08x, rt, ra, R0, true, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else {
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra, GPR const rb) {"
|
||||
" emit_%s(0x%08x, rt, ra, rb, false, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sO(GPR const rt, GPR const ra, GPR const rb) {"
|
||||
" emit_%s(0x%08x, rt, ra, rb, true, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(GPR const rt, GPR const ra, GPR const rb) {"
|
||||
" emit_%s(0x%08x, rt, ra, rb, false, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sO_(GPR const rt, GPR const ra, GPR const rb) {"
|
||||
" emit_%s(0x%08x, rt, ra, rb, true, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
}
|
||||
} else if (!strcmp(form, "X")) {
|
||||
if (!strcmp(mem, "CMPL") || !strcmp(mem, "CMP")) {
|
||||
printf(
|
||||
"void %s(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) {"
|
||||
" emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW") || !strcmp(mem, "EXTSB") || !strcmp(mem, "EXTSH") || !strcmp(mem, "EXTSW")) {
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra) {"
|
||||
" emit_%s(0x%08x, ra, rt, R0, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(GPR const rt, GPR const ra) {"
|
||||
" emit_%s(0x%08x, ra, rt, R0, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else {
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra, GPR const rb) {"
|
||||
" emit_%s(0x%08x, ra, rt, rb, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(GPR const rt, GPR const ra, GPR const rb) {"
|
||||
" emit_%s(0x%08x, ra, rt, rb, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
}
|
||||
} else if (!strcmp(form, "I")) {
|
||||
printf(
|
||||
"void %s(Label const& i) {"
|
||||
" emit_reloc_%s(0x%08x, i, false); "
|
||||
"}\n"
|
||||
, mem, form, i_opcode << 26);
|
||||
printf(
|
||||
"void %sL(Label const& i) {"
|
||||
" emit_reloc_%s(0x%08x, i, true); "
|
||||
"}\n"
|
||||
, mem, form, i_opcode << 26);
|
||||
} else if (!strcmp(form, "B")) {
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
printf(
|
||||
"void %s%s(CPR const cr, Label const& i) {"
|
||||
" emit_reloc_%s(0x%08x, %i, cr.index + %i, i, false); "
|
||||
"}\n"
|
||||
, mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1);
|
||||
printf(
|
||||
"void %s%sL(CPR const cr, Label const& i) {"
|
||||
" emit_reloc_%s(0x%08x, %i, cr.index + %i, i, true); "
|
||||
"}\n"
|
||||
, mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1);
|
||||
if (!strcmp(mem, "BC")) mem[1] = '\0';
|
||||
}
|
||||
} else if (!strcmp(form, "D")) {
|
||||
if (!strcmp(mem, "CMPLI") || !strcmp(mem, "CMPI")) {
|
||||
printf(
|
||||
"void %s(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) {"
|
||||
" emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, d); "
|
||||
"}\n"
|
||||
, mem, form, i_opcode << 26);
|
||||
} else if (!strcmp(mem, "ANDIS_") || !strcmp(mem, "ANDI_")
|
||||
|| !strcmp(mem, "ORI") || !strcmp(mem, "ORIS")
|
||||
|| !strcmp(mem, "XORI") || !strcmp(mem, "XORIS")) {
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra, uint32_t d) {"
|
||||
" emit_%s(0x%08x, ra, rt, d); "
|
||||
"}\n"
|
||||
, mem, form, i_opcode << 26);
|
||||
} else {
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra, uint32_t d) {"
|
||||
" emit_%s(0x%08x, rt, ra, d); "
|
||||
"}\n"
|
||||
, mem, form, i_opcode << 26);
|
||||
}
|
||||
} else if (!strcmp(form, "SC")) {
|
||||
printf(
|
||||
"void %s(uint32_t lev) {"
|
||||
" emit_%s(0x%08x, lev); "
|
||||
"}\n"
|
||||
, mem, form, i_opcode << 26);
|
||||
} else if (!strcmp(form, "DS")) {
|
||||
#define OP_EXT_DS ((i_opcode << 26) | (i_extopc << 0))
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra, uint32_t d) {"
|
||||
" emit_%s(0x%08x, rt, ra, d >> 2); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT_DS);
|
||||
#undef OP_EXT_DS
|
||||
} else if (!strcmp(form, "XS")) {
|
||||
#define OP_EXT_XS ((i_opcode << 26) | (i_extopc << 2))
|
||||
/* HUGE DIFFERENCE DO NOT REMOVE */
|
||||
printf(
|
||||
"void %s(GPR const rt, GPR const ra, uint32_t sh) {"
|
||||
" emit_%s(0x%08x, rt, ra, sh, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT_XS);
|
||||
printf(
|
||||
"void %s_(GPR const rt, GPR const ra, uint32_t sh) {"
|
||||
" emit_%s(0x%08x, rt, ra, sh, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT_XS);
|
||||
#undef OP_EXT_XS
|
||||
} else if (!strcmp(form, "XL")) {
|
||||
if (!strcmp(mem, "BCLR")) {
|
||||
printf(
|
||||
"void %s(GPR const bt, CPR const ba, GPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, ba.index, bb.index, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sL(GPR const bt, CPR const ba, GPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, ba.index, bb.index, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
if (!strcmp(mem, "BCLR")) mem[1] = '\0';
|
||||
for (int i = 1; i < 12; ++i) {
|
||||
printf(
|
||||
"void %s%sLR(CPR const cr) {"
|
||||
" emit_%s(0x%08x, %i, cr.index + %i, 0, false); "
|
||||
"}\n"
|
||||
, mem, infos[i].s, form, OP_EXT, infos[i].p, infos[i].o - 1);
|
||||
printf(
|
||||
"void %s%sLRL(CPR const cr) {"
|
||||
" emit_%s(0x%08x, %i, cr.index + %i, 0, true); "
|
||||
"}\n"
|
||||
, mem, infos[i].s, form, OP_EXT, infos[i].p, infos[i].o - 1);
|
||||
}
|
||||
} else if (mem[0] == 'B') {
|
||||
printf(
|
||||
"void %s(GPR const bt, CPR const ba, GPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, ba.index, bb.index, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sL(GPR const bt, CPR const ba, GPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, ba.index, bb.index, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s(GPR const bt, Cond const ba, GPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, cond2offset(ba), bb.index, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sL(GPR const bt, Cond const ba, GPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, cond2offset(ba), bb.index, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else {
|
||||
printf(
|
||||
"void %s(CPR const bt, CPR const ba, CPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, ba.index, bb.index, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %sL(CPR const bt, CPR const ba, CPR const bb) {"
|
||||
" emit_%s(0x%08x, bt.index, ba.index, bb.index, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
}
|
||||
} else if (!strcmp(form, "M")) {
|
||||
if (!strcmp(mem, "RLWNM")) {
|
||||
printf(
|
||||
"void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {"
|
||||
" emit_%s(0x%08x, ra, rs, rb.index, mb, me, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {"
|
||||
" emit_%s(0x%08x, ra, rs, rb.index, mb, me, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else {
|
||||
printf(
|
||||
"void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {"
|
||||
" emit_%s(0x%08x, ra, rs, sh, mb, me, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {"
|
||||
" emit_%s(0x%08x, ra, rs, sh, mb, me, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
}
|
||||
} else if (!strcmp(form, "MD")) {
|
||||
printf(
|
||||
"void %s(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {"
|
||||
" emit_%s(0x%08x, ra, rs, mb, sh, false); "
|
||||
"}\n"
|
||||
, mem, form, (i_opcode << 26) | (i_extopc << 2));
|
||||
printf(
|
||||
"void %s_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {"
|
||||
" emit_%s(0x%08x, ra, rs, mb, sh, true); "
|
||||
"}\n"
|
||||
, mem, form, (i_opcode << 26) | (i_extopc << 2));
|
||||
} else if (!strcmp(form, "MDS")) {
|
||||
printf(
|
||||
"void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) {"
|
||||
" emit_%s(0x%08x, ra, rs, rb, mb, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) {"
|
||||
" emit_%s(0x%08x, ra, rs, rb, mb, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else if (!strcmp(form, "A")) {
|
||||
printf(
|
||||
"void %s(FPR const frt, FPR const fra, FPR const frb, FPR const frc) {"
|
||||
" emit_%s(0x%08x, frt, fra, frb, frc, false); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
printf(
|
||||
"void %s_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) {"
|
||||
" emit_%s(0x%08x, frt, fra, frb, frc, true); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else if (!strcmp(form, "XFX")) {
|
||||
printf(
|
||||
"void %s(GPR const rt, uint32_t spr) {"
|
||||
" emit_%s(0x%08x, rt, spr); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
} else {
|
||||
printf(
|
||||
"void %s() {"
|
||||
" emit_%s(0x%08x); "
|
||||
"}\n"
|
||||
, mem, form, OP_EXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf("%s\n", line);
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
Vendored
+398
@@ -0,0 +1,398 @@
|
||||
#pragma once
|
||||
|
||||
#undef NDEBUG
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <sys/mman.h>
|
||||
#include <cstdlib>
|
||||
|
||||
//#ifndef __cpp_lib_unreachable
|
||||
namespace std {
|
||||
[[noreturn]] inline void unreachable() {
|
||||
#if defined(_MSC_VER) && !defined(__clang__) // MSVC
|
||||
__assume(false);
|
||||
#else // GCC, Clang
|
||||
__builtin_unreachable();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
namespace powah {
|
||||
|
||||
// Symbolic conditions
|
||||
enum class Cond : uint8_t {
|
||||
LT, LE, NG, EQ, GE, NL, GT, NE, SO, UN, NS, NU
|
||||
};
|
||||
|
||||
struct GPR { uint32_t index; };
|
||||
struct FPR { uint32_t index; };
|
||||
struct VPR { uint32_t index; };
|
||||
struct CPR { uint32_t index; };
|
||||
struct Label { uint32_t index; };
|
||||
|
||||
constexpr inline GPR R0{0};
|
||||
constexpr inline GPR R1{1};
|
||||
constexpr inline GPR R2{2};
|
||||
constexpr inline GPR R3{3};
|
||||
constexpr inline GPR R4{4};
|
||||
constexpr inline GPR R5{5};
|
||||
constexpr inline GPR R6{6};
|
||||
constexpr inline GPR R7{7};
|
||||
constexpr inline GPR R8{8};
|
||||
constexpr inline GPR R9{9};
|
||||
constexpr inline GPR R10{10};
|
||||
constexpr inline GPR R11{11};
|
||||
constexpr inline GPR R12{12};
|
||||
constexpr inline GPR R13{13};
|
||||
constexpr inline GPR R14{14};
|
||||
constexpr inline GPR R15{15};
|
||||
constexpr inline GPR R16{16};
|
||||
constexpr inline GPR R17{17};
|
||||
constexpr inline GPR R18{18};
|
||||
constexpr inline GPR R19{19};
|
||||
constexpr inline GPR R20{20};
|
||||
constexpr inline GPR R21{21};
|
||||
constexpr inline GPR R22{22};
|
||||
constexpr inline GPR R23{23};
|
||||
constexpr inline GPR R24{24};
|
||||
constexpr inline GPR R25{25};
|
||||
constexpr inline GPR R26{26};
|
||||
constexpr inline GPR R27{27};
|
||||
constexpr inline GPR R28{28};
|
||||
constexpr inline GPR R29{29};
|
||||
constexpr inline GPR R30{30};
|
||||
constexpr inline GPR R31{31};
|
||||
|
||||
constexpr inline FPR FR0{0};
|
||||
constexpr inline FPR FR1{1};
|
||||
constexpr inline FPR FR2{2};
|
||||
constexpr inline FPR FR3{3};
|
||||
constexpr inline FPR FR4{4};
|
||||
constexpr inline FPR FR5{5};
|
||||
constexpr inline FPR FR6{6};
|
||||
constexpr inline FPR FR7{7};
|
||||
constexpr inline FPR FR8{8};
|
||||
constexpr inline FPR FR9{9};
|
||||
constexpr inline FPR FR10{10};
|
||||
constexpr inline FPR FR11{11};
|
||||
constexpr inline FPR FR12{12};
|
||||
constexpr inline FPR FR13{13};
|
||||
constexpr inline FPR FR14{14};
|
||||
constexpr inline FPR FR15{15};
|
||||
constexpr inline FPR FR16{16};
|
||||
constexpr inline FPR FR17{17};
|
||||
constexpr inline FPR FR18{18};
|
||||
constexpr inline FPR FR19{19};
|
||||
constexpr inline FPR FR20{20};
|
||||
constexpr inline FPR FR21{21};
|
||||
constexpr inline FPR FR22{22};
|
||||
constexpr inline FPR FR23{23};
|
||||
constexpr inline FPR FR24{24};
|
||||
constexpr inline FPR FR25{25};
|
||||
constexpr inline FPR FR26{26};
|
||||
constexpr inline FPR FR27{27};
|
||||
constexpr inline FPR FR28{28};
|
||||
constexpr inline FPR FR29{29};
|
||||
constexpr inline FPR FR30{30};
|
||||
constexpr inline FPR FR31{31};
|
||||
|
||||
// They call it CPR because when programmers see this code they-
|
||||
constexpr inline CPR CR0{0};
|
||||
constexpr inline CPR CR1{4};
|
||||
constexpr inline CPR CR2{8};
|
||||
constexpr inline CPR CR3{12};
|
||||
constexpr inline CPR CR4{16};
|
||||
constexpr inline CPR CR5{20};
|
||||
constexpr inline CPR CR6{24};
|
||||
constexpr inline CPR CR7{28};
|
||||
|
||||
constexpr uint32_t XER_SO = 32;
|
||||
constexpr uint32_t XER_OV = 33;
|
||||
constexpr uint32_t XER_CA = 34;
|
||||
|
||||
enum class RelocKind : uint8_t {
|
||||
FormB,
|
||||
FormI,
|
||||
};
|
||||
struct RelocInfo {
|
||||
uint32_t offset;
|
||||
RelocKind kind;
|
||||
};
|
||||
|
||||
struct Context {
|
||||
Context() = default;
|
||||
Context(void* ptr, size_t size)
|
||||
: base{reinterpret_cast<uint32_t*>(ptr)}
|
||||
, offset{0}
|
||||
, size{uint32_t(size)} {
|
||||
|
||||
}
|
||||
~Context() = default;
|
||||
|
||||
std::vector<uint32_t> labels;
|
||||
std::vector<std::pair<uint32_t, RelocInfo>> relocs;
|
||||
|
||||
Label DefineLabel() {
|
||||
labels.push_back(0);
|
||||
return Label{ uint32_t(labels.size() - 1) };
|
||||
}
|
||||
|
||||
void ApplyRelocs() {
|
||||
for (auto const &[index, info] : relocs) {
|
||||
//assert(labels[index] != 0); //label must have an addr
|
||||
int32_t rel = (int32_t)labels[index] - (int32_t)info.offset;
|
||||
switch (info.kind) {
|
||||
case RelocKind::FormB:
|
||||
base[info.offset] |= bitExt(rel, 16, 14);
|
||||
break;
|
||||
case RelocKind::FormI:
|
||||
base[info.offset] |= bitExt(rel, 6, 24);
|
||||
break;
|
||||
}
|
||||
}
|
||||
relocs.clear();
|
||||
}
|
||||
|
||||
void LABEL(Label l) {
|
||||
assert(labels[l.index] == 0);
|
||||
labels[l.index] = offset;
|
||||
}
|
||||
|
||||
static constexpr uint32_t cond2offset(Cond c) noexcept {
|
||||
switch (c) {
|
||||
case Cond::LT: return 1;
|
||||
case Cond::LE: return 2;
|
||||
case Cond::NG: return 2;
|
||||
case Cond::EQ: return 3;
|
||||
case Cond::GE: return 1;
|
||||
case Cond::NL: return 1;
|
||||
case Cond::GT: return 2;
|
||||
case Cond::NE: return 3;
|
||||
case Cond::SO: return 4;
|
||||
case Cond::UN: return 4;
|
||||
case Cond::NS: return 4;
|
||||
case Cond::NU: return 4;
|
||||
default: return 0; //hopefully icc isn't stupid
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bitExt(uint32_t value, uint32_t offs, uint32_t n) {
|
||||
uint32_t mask = (1UL << n) - 1;
|
||||
return (value & mask) << (32 - (n + offs));
|
||||
}
|
||||
void emit_XO(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool oe, bool rc) {
|
||||
base[offset++] = (op |
|
||||
bitExt(rt.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| bitExt(rb.index, 16, 5)
|
||||
| bitExt(oe, 21, 1)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_D(uint32_t op, GPR const rt, GPR const ra, uint32_t d) {
|
||||
base[offset++] = (op |
|
||||
bitExt(rt.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| (d & 0xffff)
|
||||
);
|
||||
}
|
||||
void emit_X(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool rc) {
|
||||
base[offset++] = (op |
|
||||
bitExt(rt.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| bitExt(rb.index, 16, 5)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_XS(uint32_t op, GPR const rt, GPR const ra, uint32_t sh, bool rc) {
|
||||
base[offset++] = (op |
|
||||
((rt.index & 0x1f) << 16)
|
||||
| ((ra.index & 0x1f) << 21)
|
||||
| ((sh & 0x1f) << 11)
|
||||
| ((sh >> 4) & 0x02)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_reloc_I(uint32_t op, Label const& l, bool lk) {
|
||||
relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormI });
|
||||
base[offset++] = (op |
|
||||
bitExt(lk, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_reloc_B(uint32_t op, uint32_t bo, uint32_t cri, Label const& l, bool lk) {
|
||||
relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormB });
|
||||
base[offset++] = (op |
|
||||
bitExt(bo, 6, 5)
|
||||
| bitExt(cri, 11, 5)
|
||||
| bitExt(lk, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_XL(uint32_t op, uint32_t bt, uint32_t ba, uint32_t bb, bool lk) {
|
||||
base[offset++] = (op |
|
||||
bitExt(bt, 6, 5)
|
||||
| bitExt(ba, 11, 5)
|
||||
| bitExt(bb, 16, 5)
|
||||
| bitExt(lk, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_A(uint32_t op, FPR const frt, FPR const fra, FPR const frb, FPR const frc, bool rc) {
|
||||
base[offset++] = (op |
|
||||
bitExt(frt.index, 6, 5)
|
||||
| bitExt(fra.index, 11, 5)
|
||||
| bitExt(frb.index, 16, 5)
|
||||
| bitExt(frc.index, 21, 5)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_DS(uint32_t op, GPR const rt, GPR const ra, uint32_t d) {
|
||||
//assert(d & 0x03 == 0);
|
||||
base[offset++] = (op |
|
||||
bitExt(rt.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| bitExt(d, 16, 14)
|
||||
);
|
||||
}
|
||||
void emit_M(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me, bool rc) {
|
||||
assert(sh <= 0x3f && mb <= 0x3f);
|
||||
base[offset++] = (op |
|
||||
bitExt(rs.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| ((sh & 0x1f) << 11)
|
||||
| ((mb & 0x1f) << 6)
|
||||
| ((me & 0x1f) << 1)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_MD(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) {
|
||||
assert(mb <= 0x3f);
|
||||
base[offset++] = (op |
|
||||
bitExt(rs.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| bitExt(rb.index, 16, 5)
|
||||
| ((mb & 0x1f) << 6) | (mb & 0x20)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_MD(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, bool rc) {
|
||||
assert(sh <= 0x3f && mb <= 0x3f);
|
||||
base[offset++] = (op |
|
||||
bitExt(rs.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| ((mb & 0x1f) << 6) | (mb & 0x20)
|
||||
| ((sh & 0x1f) << 11) | ((sh >> 4) & 0x02)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_MDS(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) {
|
||||
base[offset++] = (op |
|
||||
bitExt(rs.index, 6, 5)
|
||||
| bitExt(ra.index, 11, 5)
|
||||
| bitExt(rb.index, 16, 5)
|
||||
| ((mb & 0x1f) << 6) | (mb & 0x20)
|
||||
| bitExt(rc, 31, 1)
|
||||
);
|
||||
}
|
||||
void emit_XFL(uint32_t op) {
|
||||
(void)op;
|
||||
std::abort();
|
||||
}
|
||||
void emit_XFX(uint32_t op, GPR const rt, uint32_t spr) {
|
||||
base[offset++] = (op |
|
||||
(rt.index & 0x1f) << 21
|
||||
| ((spr & 0xff) << 12)
|
||||
);
|
||||
}
|
||||
void emit_SC(uint32_t op, uint32_t lev) {
|
||||
(void)op;
|
||||
(void)lev;
|
||||
std::abort();
|
||||
}
|
||||
|
||||
// Extended Memmonics, hand coded :)
|
||||
void MR(GPR const ra, GPR const rs) { OR(ra, rs, rs); }
|
||||
void NOP() { ORI(R0, R0, 0); }
|
||||
void NOT(GPR const ra, GPR const rs) { NOR(ra, rs, rs); }
|
||||
|
||||
void ROTLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, n, 0); }
|
||||
void ROTRDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 64 - n, 0); }
|
||||
|
||||
void ROTLWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, n, 0, 31); }
|
||||
void ROTRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, 0, 31); }
|
||||
|
||||
void ROTLW(GPR const ra, GPR const rs, GPR const rb) { RLWNM(ra, rs, rb, 0, 31); }
|
||||
void ROTLD(GPR const ra, GPR const rs, GPR const rb) { RLDCL(ra, rs, rb, 0); }
|
||||
|
||||
void EXTLDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICR(ra, rs, b, n - 1); }
|
||||
void SLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICR(ra, rs, n, 63 - n); }
|
||||
void CLRLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 0, n); }
|
||||
|
||||
void EXTRDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICL(ra, rs, b + n, 64 - n); }
|
||||
void SRDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 64 - n, n); }
|
||||
void CLLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICR(ra, rs, 0, n); }
|
||||
void CLRSLDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICR(ra, rs, n, b - n); }
|
||||
|
||||
void EXTLWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, b, 0, n - 1); }
|
||||
void SRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, n, 31); }
|
||||
void CLRRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 0, 0, 31 - n); }
|
||||
|
||||
void CRSET(CPR const bx) { CREQV(bx, bx, bx); }
|
||||
void CRCLR(CPR const bx) { CRXOR(bx, bx, bx); }
|
||||
void CRMOVE(CPR const bx, CPR const by) { CROR(bx, by, by); }
|
||||
void CRNOT(CPR const bx, CPR const by) { CRNOR(bx, by, by); }
|
||||
|
||||
void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 1, rx, v); }
|
||||
void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 0, rx, v); }
|
||||
void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 1, rx, ry); }
|
||||
void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 0, rx, ry); }
|
||||
void CMPLDI(GPR const rx, uint32_t v) { CMPLI(0, 1, rx, v); }
|
||||
void CMPLWI(GPR const rx, uint32_t v) { CMPLI(0, 0, rx, v); }
|
||||
void CMPLD(GPR const rx, GPR const ry) { CMPL(0, 1, rx, ry); }
|
||||
void CMPLW(GPR const rx, GPR const ry) { CMPL(0, 0, rx, ry); }
|
||||
|
||||
void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index, 0, rx, si); }
|
||||
void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 0, rx, ry); }
|
||||
void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index, 1, rx, si); }
|
||||
void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 1, rx, ry); }
|
||||
void CMPWI(GPR const rx, uint32_t si) { CMPI(0, 0, rx, si); }
|
||||
void CMPW(GPR const rx, GPR const ry) { CMP(0, 0, rx, ry); }
|
||||
void CMPDI(GPR const rx, uint32_t si) { CMPI(0, 1, rx, si); }
|
||||
void CMPD(GPR const rx, GPR const ry) { CMP(0, 1, rx, ry); }
|
||||
|
||||
void LI(GPR const rx, uint32_t value) { ADDI(rx, R0, value); }
|
||||
void LIS(GPR const rx, uint32_t value) { ADDIS(rx, R0, value); }
|
||||
|
||||
void MFLR(GPR const rt) { MFSPR(powah::GPR{8}, rt, powah::GPR{0}); }
|
||||
void MTLR(GPR const rt) { MTSPR(powah::GPR{8}, rt, powah::GPR{0}); }
|
||||
void BLR() { base[offset++] = 0x4e800020; } //BCLR(R0, CR0, R0);
|
||||
|
||||
void MFCTR(GPR const rt) { MFSPR(powah::GPR{9}, rt, powah::GPR{0}); }
|
||||
void MTCTR(GPR const rt) { MTSPR(powah::GPR{9}, rt, powah::GPR{0}); }
|
||||
void BCTRL() { base[offset++] = 0x4e800421; } //BCCTRL(R0, CR0, R0);
|
||||
void BCTR() { base[offset++] = 0x4e800420; } //BCCTR(R0, CR0, R0);
|
||||
|
||||
// TODO: PowerPC 11 stuff
|
||||
void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) {
|
||||
(void)rd;
|
||||
(void)ra;
|
||||
(void)rb;
|
||||
(void)d;
|
||||
std::unreachable();
|
||||
}
|
||||
void ISELLT(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 0); }
|
||||
void ISELGT(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 1); }
|
||||
void ISELEQ(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 2); }
|
||||
|
||||
// Rawly pasted because fuck you
|
||||
#include "powah_gen_base.hpp"
|
||||
|
||||
uint32_t* base = nullptr;
|
||||
uint32_t offset = 0;
|
||||
uint32_t size = 0;
|
||||
};
|
||||
|
||||
}
|
||||
Vendored
+484
@@ -0,0 +1,484 @@
|
||||
// this file is autogenerated DO NOT MODIFY
|
||||
#pragma once
|
||||
void ADD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, false, false); }
|
||||
void ADDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, true, false); }
|
||||
void ADD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, false, true); }
|
||||
void ADDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, true, true); }
|
||||
void ADDC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, false, false); }
|
||||
void ADDCO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, true, false); }
|
||||
void ADDC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, false, true); }
|
||||
void ADDCO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, true, true); }
|
||||
void ADDE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, false, false); }
|
||||
void ADDEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, true, false); }
|
||||
void ADDE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, false, true); }
|
||||
void ADDEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, true, true); }
|
||||
void ADDI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x38000000, rt, ra, d); }
|
||||
void ADDIC(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); }
|
||||
void ADDIC_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); }
|
||||
void ADDIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x3c000000, rt, ra, d); }
|
||||
void ADDME(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, false, false); }
|
||||
void ADDMEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, true, false); }
|
||||
void ADDME_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, false, true); }
|
||||
void ADDMEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, true, true); }
|
||||
void ADDZE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, false, false); }
|
||||
void ADDZEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, true, false); }
|
||||
void ADDZE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, false, true); }
|
||||
void ADDZEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, true, true); }
|
||||
void AND(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000038, ra, rt, rb, false); }
|
||||
void AND_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000038, ra, rt, rb, true); }
|
||||
void ANDC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, ra, rt, rb, false); }
|
||||
void ANDC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, ra, rt, rb, true); }
|
||||
void ANDI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x70000000, ra, rt, d); }
|
||||
void ANDIS_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x74000000, ra, rt, d); }
|
||||
void B(Label const& i) { emit_reloc_I(0x48000000, i, false); }
|
||||
void BL(Label const& i) { emit_reloc_I(0x48000000, i, true); }
|
||||
void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, false); }
|
||||
void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, true); }
|
||||
void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, false); }
|
||||
void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, true); }
|
||||
void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); }
|
||||
void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); }
|
||||
void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); }
|
||||
void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); }
|
||||
void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, false); }
|
||||
void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, true); }
|
||||
void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); }
|
||||
void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); }
|
||||
void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); }
|
||||
void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); }
|
||||
void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, false); }
|
||||
void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, true); }
|
||||
void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, false); }
|
||||
void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, true); }
|
||||
void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); }
|
||||
void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); }
|
||||
void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); }
|
||||
void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); }
|
||||
void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, false); }
|
||||
void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, true); }
|
||||
void BCCTR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, false); }
|
||||
void BCCTRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, true); }
|
||||
void BCCTR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, false); }
|
||||
void BCCTRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, true); }
|
||||
void BCLR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, false); }
|
||||
void BCLRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, true); }
|
||||
void BLTLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 0, 0, false); }
|
||||
void BLTLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 0, 0, true); }
|
||||
void BLELR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, false); }
|
||||
void BLELRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, true); }
|
||||
void BNGLR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, false); }
|
||||
void BNGLRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, true); }
|
||||
void BEQLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 2, 0, false); }
|
||||
void BEQLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 2, 0, true); }
|
||||
void BGELR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, false); }
|
||||
void BGELRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, true); }
|
||||
void BNLLR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, false); }
|
||||
void BNLLRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, true); }
|
||||
void BGTLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 1, 0, false); }
|
||||
void BGTLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 1, 0, true); }
|
||||
void BNELR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 2, 0, false); }
|
||||
void BNELRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 2, 0, true); }
|
||||
void BSOLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, false); }
|
||||
void BSOLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, true); }
|
||||
void BUNLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, false); }
|
||||
void BUNLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, true); }
|
||||
void BNSLR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 3, 0, false); }
|
||||
void BNSLRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 3, 0, true); }
|
||||
void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); }
|
||||
void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, GPR{(bf << 2) | l}, ra, d); }
|
||||
void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000040, GPR{(bf << 2) | l}, ra, rb, false); }
|
||||
void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, GPR{(bf << 2) | l}, ra, d); }
|
||||
void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, ra, rt, R0, false); }
|
||||
void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, ra, rt, R0, true); }
|
||||
void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, ra, rt, R0, false); }
|
||||
void CNTLZW_(GPR const rt, GPR const ra) { emit_X(0x7c000034, ra, rt, R0, true); }
|
||||
void CRAND(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000202, bt.index, ba.index, bb.index, false); }
|
||||
void CRANDL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000202, bt.index, ba.index, bb.index, true); }
|
||||
void CRANDC(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000102, bt.index, ba.index, bb.index, false); }
|
||||
void CRANDCL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000102, bt.index, ba.index, bb.index, true); }
|
||||
void CREQV(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000242, bt.index, ba.index, bb.index, false); }
|
||||
void CREQVL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000242, bt.index, ba.index, bb.index, true); }
|
||||
void CRNAND(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c0001c2, bt.index, ba.index, bb.index, false); }
|
||||
void CRNANDL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c0001c2, bt.index, ba.index, bb.index, true); }
|
||||
void CRNOR(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000042, bt.index, ba.index, bb.index, false); }
|
||||
void CRNORL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000042, bt.index, ba.index, bb.index, true); }
|
||||
void CROR(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000382, bt.index, ba.index, bb.index, false); }
|
||||
void CRORL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000382, bt.index, ba.index, bb.index, true); }
|
||||
void CRORC(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000342, bt.index, ba.index, bb.index, false); }
|
||||
void CRORCL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000342, bt.index, ba.index, bb.index, true); }
|
||||
void CRXOR(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000182, bt.index, ba.index, bb.index, false); }
|
||||
void CRXORL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000182, bt.index, ba.index, bb.index, true); }
|
||||
void DCBF(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, ra, rt, rb, false); }
|
||||
void DCBF_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, ra, rt, rb, true); }
|
||||
void DCBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, ra, rt, rb, false); }
|
||||
void DCBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, ra, rt, rb, true); }
|
||||
void DCBST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, ra, rt, rb, false); }
|
||||
void DCBST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, ra, rt, rb, true); }
|
||||
void DCBT(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, ra, rt, rb, false); }
|
||||
void DCBT_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, ra, rt, rb, true); }
|
||||
void DCBTST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, ra, rt, rb, false); }
|
||||
void DCBTST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, ra, rt, rb, true); }
|
||||
void DCBZ(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ec, ra, rt, rb, false); }
|
||||
void DCBZ_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ec, ra, rt, rb, true); }
|
||||
void DIVD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, false, false); }
|
||||
void DIVDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, true, false); }
|
||||
void DIVD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, false, true); }
|
||||
void DIVDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, true, true); }
|
||||
void DIVDU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, false, false); }
|
||||
void DIVDUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, true, false); }
|
||||
void DIVDU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, false, true); }
|
||||
void DIVDUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, true, true); }
|
||||
void DIVW(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, false, false); }
|
||||
void DIVWO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, true, false); }
|
||||
void DIVW_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, false, true); }
|
||||
void DIVWO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, true, true); }
|
||||
void DIVWU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, false, false); }
|
||||
void DIVWUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, true, false); }
|
||||
void DIVWU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, false, true); }
|
||||
void DIVWUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, true, true); }
|
||||
void ECIWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00026c, ra, rt, rb, false); }
|
||||
void ECIWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00026c, ra, rt, rb, true); }
|
||||
void ECOWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036c, ra, rt, rb, false); }
|
||||
void ECOWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036c, ra, rt, rb, true); }
|
||||
void EIEIO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, ra, rt, rb, false); }
|
||||
void EIEIO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, ra, rt, rb, true); }
|
||||
void EQV(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, ra, rt, rb, false); }
|
||||
void EQV_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, ra, rt, rb, true); }
|
||||
void EXTSB(GPR const rt, GPR const ra) { emit_X(0x7c000774, ra, rt, R0, false); }
|
||||
void EXTSB_(GPR const rt, GPR const ra) { emit_X(0x7c000774, ra, rt, R0, true); }
|
||||
void EXTSH(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, false); }
|
||||
void EXTSHC(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, false); }
|
||||
void EXTSH_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, true); }
|
||||
void EXTSHC_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, true); }
|
||||
void EXTSW(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, ra, rt, R0, false); }
|
||||
void EXTSW_(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, ra, rt, R0, true); }
|
||||
void FABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, ra, rt, rb, false); }
|
||||
void FABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, ra, rt, rb, true); }
|
||||
void FADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, false); }
|
||||
void FADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, true); }
|
||||
void FADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00002a, frt, fra, frb, frc, false); }
|
||||
void FADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00002a, frt, fra, frb, frc, true); }
|
||||
void FCFID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, ra, rt, rb, false); }
|
||||
void FCFID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, ra, rt, rb, true); }
|
||||
void FCMPO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, ra, rt, rb, false); }
|
||||
void FCMPO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, ra, rt, rb, true); }
|
||||
void FCMPU(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc000000, bt.index, ba.index, bb.index, false); }
|
||||
void FCMPUL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc000000, bt.index, ba.index, bb.index, true); }
|
||||
void FCTID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, ra, rt, rb, false); }
|
||||
void FCTID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, ra, rt, rb, true); }
|
||||
void FCTIDZ(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, ra, rt, rb, false); }
|
||||
void FCTIDZ_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, ra, rt, rb, true); }
|
||||
void FCTIW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, ra, rt, rb, false); }
|
||||
void FCTIW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, ra, rt, rb, true); }
|
||||
void FCTIWZ(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc00001e, bt.index, ba.index, bb.index, false); }
|
||||
void FCTIWZL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc00001e, bt.index, ba.index, bb.index, true); }
|
||||
void FDIV(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000024, frt, fra, frb, frc, false); }
|
||||
void FDIV_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000024, frt, fra, frb, frc, true); }
|
||||
void FDIVS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000024, frt, fra, frb, frc, false); }
|
||||
void FDIVS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000024, frt, fra, frb, frc, true); }
|
||||
void FMADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003a, frt, fra, frb, frc, false); }
|
||||
void FMADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003a, frt, fra, frb, frc, true); }
|
||||
void FMADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003a, frt, fra, frb, frc, false); }
|
||||
void FMADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003a, frt, fra, frb, frc, true); }
|
||||
void FMR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, ra, rt, rb, false); }
|
||||
void FMR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, ra, rt, rb, true); }
|
||||
void FMSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000038, frt, fra, frb, frc, false); }
|
||||
void FMSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000038, frt, fra, frb, frc, true); }
|
||||
void FMSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000038, frt, fra, frb, frc, false); }
|
||||
void FMSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000038, frt, fra, frb, frc, true); }
|
||||
void FMUL(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000032, frt, fra, frb, frc, false); }
|
||||
void FMUL_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000032, frt, fra, frb, frc, true); }
|
||||
void FMULS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000032, frt, fra, frb, frc, false); }
|
||||
void FMULS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000032, frt, fra, frb, frc, true); }
|
||||
void FNABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, ra, rt, rb, false); }
|
||||
void FNABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, ra, rt, rb, true); }
|
||||
void FNEG(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, ra, rt, rb, false); }
|
||||
void FNEG_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, ra, rt, rb, true); }
|
||||
void FNMADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003e, frt, fra, frb, frc, false); }
|
||||
void FNMADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003e, frt, fra, frb, frc, true); }
|
||||
void FNMADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003e, frt, fra, frb, frc, false); }
|
||||
void FNMADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003e, frt, fra, frb, frc, true); }
|
||||
void FNMSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003c, frt, fra, frb, frc, false); }
|
||||
void FNMSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003c, frt, fra, frb, frc, true); }
|
||||
void FNMSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003c, frt, fra, frb, frc, false); }
|
||||
void FNMSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003c, frt, fra, frb, frc, true); }
|
||||
void FRES(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000030, frt, fra, frb, frc, false); }
|
||||
void FRES_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000030, frt, fra, frb, frc, true); }
|
||||
void FRSP(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, ra, rt, rb, false); }
|
||||
void FRSP_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, ra, rt, rb, true); }
|
||||
void FRSQRTE(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000034, frt, fra, frb, frc, false); }
|
||||
void FRSQRTE_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000034, frt, fra, frb, frc, true); }
|
||||
void FSEL(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002e, frt, fra, frb, frc, false); }
|
||||
void FSEL_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002e, frt, fra, frb, frc, true); }
|
||||
void FSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000028, frt, fra, frb, frc, false); }
|
||||
void FSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000028, frt, fra, frb, frc, true); }
|
||||
void FSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000028, frt, fra, frb, frc, false); }
|
||||
void FSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000028, frt, fra, frb, frc, true); }
|
||||
void ICBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, ra, rt, rb, false); }
|
||||
void ICBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, ra, rt, rb, true); }
|
||||
void ISYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, ra, rt, rb, false); }
|
||||
void ISYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, ra, rt, rb, true); }
|
||||
void LBZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x88000000, rt, ra, d); }
|
||||
void LBZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x8c000000, rt, ra, d); }
|
||||
void LBZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, ra, rt, rb, false); }
|
||||
void LBZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, ra, rt, rb, true); }
|
||||
void LBZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, ra, rt, rb, false); }
|
||||
void LBZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, ra, rt, rb, true); }
|
||||
void LD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000000, rt, ra, d >> 2); }
|
||||
void LDARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, false); }
|
||||
void LDARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, true); }
|
||||
void LDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000001, rt, ra, d >> 2); }
|
||||
void LDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, false); }
|
||||
void LDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, true); }
|
||||
void LDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, ra, rt, rb, false); }
|
||||
void LDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, ra, rt, rb, true); }
|
||||
void LFD(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc8000000, rt, ra, d); }
|
||||
void LFDU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xcc000000, rt, ra, d); }
|
||||
void LFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, ra, rt, rb, false); }
|
||||
void LFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, ra, rt, rb, true); }
|
||||
void LFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, ra, rt, rb, false); }
|
||||
void LFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, ra, rt, rb, true); }
|
||||
void LFS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc0000000, rt, ra, d); }
|
||||
void LFSU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc4000000, rt, ra, d); }
|
||||
void LFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, ra, rt, rb, false); }
|
||||
void LFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, ra, rt, rb, true); }
|
||||
void LFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, ra, rt, rb, false); }
|
||||
void LFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, ra, rt, rb, true); }
|
||||
void LHA(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa8000000, rt, ra, d); }
|
||||
void LHAU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xac000000, rt, ra, d); }
|
||||
void LHAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, ra, rt, rb, false); }
|
||||
void LHAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, ra, rt, rb, true); }
|
||||
void LHAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, ra, rt, rb, false); }
|
||||
void LHAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, ra, rt, rb, true); }
|
||||
void LHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, ra, rt, rb, false); }
|
||||
void LHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, ra, rt, rb, true); }
|
||||
void LHZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa0000000, rt, ra, d); }
|
||||
void LHZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa4000000, rt, ra, d); }
|
||||
void LHZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, ra, rt, rb, false); }
|
||||
void LHZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, ra, rt, rb, true); }
|
||||
void LHZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, ra, rt, rb, false); }
|
||||
void LHZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, ra, rt, rb, true); }
|
||||
void LMW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb8000000, rt, ra, d); }
|
||||
void LSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, rb, false); }
|
||||
void LSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, rb, true); }
|
||||
void LSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, false); }
|
||||
void LSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, true); }
|
||||
void LWA(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000002, rt, ra, d >> 2); }
|
||||
void LWARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, false); }
|
||||
void LWARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, true); }
|
||||
void LWAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, ra, rt, rb, false); }
|
||||
void LWAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, ra, rt, rb, true); }
|
||||
void LWAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, ra, rt, rb, false); }
|
||||
void LWAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, ra, rt, rb, true); }
|
||||
void LWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, ra, rt, rb, false); }
|
||||
void LWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, ra, rt, rb, true); }
|
||||
void LWZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x80000000, rt, ra, d); }
|
||||
void LWZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x84000000, rt, ra, d); }
|
||||
void LWZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, ra, rt, rb, false); }
|
||||
void LWZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, ra, rt, rb, true); }
|
||||
void LWZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, ra, rt, rb, false); }
|
||||
void LWZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, ra, rt, rb, true); }
|
||||
void MCRF(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000000, bt.index, ba.index, bb.index, false); }
|
||||
void MCRFL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000000, bt.index, ba.index, bb.index, true); }
|
||||
void MCRFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, ra, rt, rb, false); }
|
||||
void MCRFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, ra, rt, rb, true); }
|
||||
void MCRXR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, ra, rt, rb, false); }
|
||||
void MCRXR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, ra, rt, rb, true); }
|
||||
void MFCR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, ra, rt, rb, false); }
|
||||
void MFCR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, ra, rt, rb, true); }
|
||||
void MFFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, ra, rt, rb, false); }
|
||||
void MFFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, ra, rt, rb, true); }
|
||||
void MFMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, ra, rt, rb, false); }
|
||||
void MFMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, ra, rt, rb, true); }
|
||||
void MFSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, ra, rt, rb, false); }
|
||||
void MFSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, ra, rt, rb, true); }
|
||||
void MFSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, ra, rt, rb, false); }
|
||||
void MFSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, ra, rt, rb, true); }
|
||||
void MFSRIN(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, ra, rt, rb, false); }
|
||||
void MFSRIN_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, ra, rt, rb, true); }
|
||||
void MTCRF(GPR const rt, uint32_t spr) { emit_XFX(0x7c000120, rt, spr); }
|
||||
void MTFSB0(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, ra, rt, rb, false); }
|
||||
void MTFSB0_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, ra, rt, rb, true); }
|
||||
void MTFSB1(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, ra, rt, rb, false); }
|
||||
void MTFSB1_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, ra, rt, rb, true); }
|
||||
void MTFSF() { emit_XFL(0xfc00058e); }
|
||||
void MTFSFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, ra, rt, rb, false); }
|
||||
void MTFSFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, ra, rt, rb, true); }
|
||||
void MTMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, ra, rt, rb, false); }
|
||||
void MTMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, ra, rt, rb, true); }
|
||||
void MTSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, ra, rt, rb, false); }
|
||||
void MTSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, ra, rt, rb, true); }
|
||||
void MTSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, ra, rt, rb, false); }
|
||||
void MTSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, ra, rt, rb, true); }
|
||||
void MTSRIN(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001e4, ra, rt, rb, false); }
|
||||
void MTSRIN_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001e4, ra, rt, rb, true); }
|
||||
void MULHD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, false, false); }
|
||||
void MULHDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, true, false); }
|
||||
void MULHD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, false, true); }
|
||||
void MULHDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, true, true); }
|
||||
void MULHDU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, false, false); }
|
||||
void MULHDUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, true, false); }
|
||||
void MULHDU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, false, true); }
|
||||
void MULHDUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, true, true); }
|
||||
void MULHW(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, false, false); }
|
||||
void MULHWO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, true, false); }
|
||||
void MULHW_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, false, true); }
|
||||
void MULHWO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, true, true); }
|
||||
void MULHWU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, false, false); }
|
||||
void MULHWUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, true, false); }
|
||||
void MULHWU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, false, true); }
|
||||
void MULHWUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, true, true); }
|
||||
void MULLD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, false, false); }
|
||||
void MULLDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, true, false); }
|
||||
void MULLD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, false, true); }
|
||||
void MULLDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, true, true); }
|
||||
void MULLI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x1c000000, rt, ra, d); }
|
||||
void MULLW(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, false, false); }
|
||||
void MULLWO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, true, false); }
|
||||
void MULLW_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, false, true); }
|
||||
void MULLWO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, true, true); }
|
||||
void NAND(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003b8, ra, rt, rb, false); }
|
||||
void NAND_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003b8, ra, rt, rb, true); }
|
||||
void NEG(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, false, false); }
|
||||
void NEGO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, true, false); }
|
||||
void NEG_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, false, true); }
|
||||
void NEGO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, true, true); }
|
||||
void NOR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000f8, ra, rt, rb, false); }
|
||||
void NOR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000f8, ra, rt, rb, true); }
|
||||
void OR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000378, ra, rt, rb, false); }
|
||||
void OR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000378, ra, rt, rb, true); }
|
||||
void ORC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, ra, rt, rb, false); }
|
||||
void ORC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, ra, rt, rb, true); }
|
||||
void ORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x60000000, ra, rt, d); }
|
||||
void ORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x64000000, ra, rt, d); }
|
||||
void RFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, ra, rt, rb, false); }
|
||||
void RFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, ra, rt, rb, true); }
|
||||
void RLDCL(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, ra, rs, rb, mb, false); }
|
||||
void RLDCL_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, ra, rs, rb, mb, true); }
|
||||
void RLDCR(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, ra, rs, rb, mb, false); }
|
||||
void RLDCR_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, ra, rs, rb, mb, true); }
|
||||
void RLDIC(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, ra, rs, mb, sh, false); }
|
||||
void RLDIC_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, ra, rs, mb, sh, true); }
|
||||
void RLDICL(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, ra, rs, mb, sh, false); }
|
||||
void RLDICL_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, ra, rs, mb, sh, true); }
|
||||
void RLDICR(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, ra, rs, mb, sh, false); }
|
||||
void RLDICR_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, ra, rs, mb, sh, true); }
|
||||
void RLDIMI(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, ra, rs, mb, sh, false); }
|
||||
void RLDIMI_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, ra, rs, mb, sh, true); }
|
||||
void RLWIMI(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, ra, rs, sh, mb, me, false); }
|
||||
void RLWIMI_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, ra, rs, sh, mb, me, true); }
|
||||
void RLWINM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, ra, rs, sh, mb, me, false); }
|
||||
void RLWINM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, ra, rs, sh, mb, me, true); }
|
||||
void RLWNM(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, ra, rs, rb.index, mb, me, false); }
|
||||
void RLWNM_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, ra, rs, rb.index, mb, me, true); }
|
||||
void SC(uint32_t lev) { emit_SC(0x44000000, lev); }
|
||||
void SI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); }
|
||||
void SI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); }
|
||||
void SLBIA(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, ra, rt, rb, false); }
|
||||
void SLBIA_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, ra, rt, rb, true); }
|
||||
void SLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, ra, rt, rb, false); }
|
||||
void SLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, ra, rt, rb, true); }
|
||||
void SLD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, ra, rt, rb, false); }
|
||||
void SLD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, ra, rt, rb, true); }
|
||||
void SLW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, rb, false); }
|
||||
void SLW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, rb, true); }
|
||||
void SRAD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, false); }
|
||||
void SRAD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, true); }
|
||||
void SRADI(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, rt, ra, sh, false); }
|
||||
void SRADI_(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, rt, ra, sh, true); }
|
||||
void SRD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, false); }
|
||||
void SRD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, true); }
|
||||
void SRAW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, ra, rt, rb, false); }
|
||||
void SRAW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, ra, rt, rb, true); }
|
||||
void SRAWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, ra, rt, rb, false); }
|
||||
void SRAWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, ra, rt, rb, true); }
|
||||
void SRW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, ra, rt, rb, false); }
|
||||
void SRW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, ra, rt, rb, true); }
|
||||
void STB(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x98000000, rt, ra, d); }
|
||||
void STBU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x9c000000, rt, ra, d); }
|
||||
void STBUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, ra, rt, rb, false); }
|
||||
void STBUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, ra, rt, rb, true); }
|
||||
void STBX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, ra, rt, rb, false); }
|
||||
void STBX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, ra, rt, rb, true); }
|
||||
void STD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000000, rt, ra, d >> 2); }
|
||||
void STDCX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, false); }
|
||||
void STDCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, true); }
|
||||
void STDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000001, rt, ra, d >> 2); }
|
||||
void STDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, false); }
|
||||
void STDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, true); }
|
||||
void STDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, ra, rt, rb, false); }
|
||||
void STDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, ra, rt, rb, true); }
|
||||
void STFD(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd8000000, rt, ra, d); }
|
||||
void STFDU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xdc000000, rt, ra, d); }
|
||||
void STFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, ra, rt, rb, false); }
|
||||
void STFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, ra, rt, rb, true); }
|
||||
void STFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, ra, rt, rb, false); }
|
||||
void STFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, ra, rt, rb, true); }
|
||||
void STFIWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, ra, rt, rb, false); }
|
||||
void STFIWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, ra, rt, rb, true); }
|
||||
void STFS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd0000000, rt, ra, d); }
|
||||
void STFSU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd4000000, rt, ra, d); }
|
||||
void STFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, ra, rt, rb, false); }
|
||||
void STFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, ra, rt, rb, true); }
|
||||
void STFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, ra, rt, rb, false); }
|
||||
void STFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, ra, rt, rb, true); }
|
||||
void STH(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb0000000, rt, ra, d); }
|
||||
void STHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, ra, rt, rb, false); }
|
||||
void STHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, ra, rt, rb, true); }
|
||||
void STHU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb4000000, rt, ra, d); }
|
||||
void STHUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, ra, rt, rb, false); }
|
||||
void STHUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, ra, rt, rb, true); }
|
||||
void STHX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, ra, rt, rb, false); }
|
||||
void STHX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, ra, rt, rb, true); }
|
||||
void STMW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xbc000000, rt, ra, d); }
|
||||
void STSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, ra, rt, rb, false); }
|
||||
void STSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, ra, rt, rb, true); }
|
||||
void STSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, ra, rt, rb, false); }
|
||||
void STSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, ra, rt, rb, true); }
|
||||
void STW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x90000000, rt, ra, d); }
|
||||
void STWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, ra, rt, rb, false); }
|
||||
void STWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, ra, rt, rb, true); }
|
||||
void STWCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, ra, rt, rb, false); }
|
||||
void STWCX__(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, ra, rt, rb, true); }
|
||||
void STWU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x94000000, rt, ra, d); }
|
||||
void STWUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, ra, rt, rb, false); }
|
||||
void STWUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, ra, rt, rb, true); }
|
||||
void STWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012e, ra, rt, rb, false); }
|
||||
void STWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012e, ra, rt, rb, true); }
|
||||
void SUBF(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, false, false); }
|
||||
void SUBFO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, true, false); }
|
||||
void SUBF_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, false, true); }
|
||||
void SUBFO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, true, true); }
|
||||
void SUBFC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, false, false); }
|
||||
void SUBFCO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, true, false); }
|
||||
void SUBFC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, false, true); }
|
||||
void SUBFCO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, true, true); }
|
||||
void SUBFE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, false, false); }
|
||||
void SUBFEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, true, false); }
|
||||
void SUBFE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, false, true); }
|
||||
void SUBFEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, true, true); }
|
||||
void SUBFIC(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x20000000, rt, ra, d); }
|
||||
void SUBFME(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, false, false); }
|
||||
void SUBFMEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, true, false); }
|
||||
void SUBFME_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, false, true); }
|
||||
void SUBFMEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, true, true); }
|
||||
void SUBFZE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, false, false); }
|
||||
void SUBFZEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, true, false); }
|
||||
void SUBFZE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, false, true); }
|
||||
void SUBFZEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, true, true); }
|
||||
void SYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ac, ra, rt, rb, false); }
|
||||
void SYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ac, ra, rt, rb, true); }
|
||||
void TD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000088, ra, rt, rb, false); }
|
||||
void TD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000088, ra, rt, rb, true); }
|
||||
void TDI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x08000000, rt, ra, d); }
|
||||
void TLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, ra, rt, rb, false); }
|
||||
void TLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, ra, rt, rb, true); }
|
||||
void TLBSYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, ra, rt, rb, false); }
|
||||
void TLBSYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, ra, rt, rb, true); }
|
||||
void TW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, ra, rt, rb, false); }
|
||||
void TW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, ra, rt, rb, true); }
|
||||
void TWI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x0c000000, rt, ra, d); }
|
||||
void XOR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, ra, rt, rb, false); }
|
||||
void XOR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, ra, rt, rb, true); }
|
||||
void XORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x68000000, ra, rt, d); }
|
||||
void XORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x6c000000, ra, rt, d); }
|
||||
Vendored
+340
@@ -0,0 +1,340 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <sys/mman.h>
|
||||
#include "powah_emit.hpp"
|
||||
|
||||
#define EB32(X) __bswap32(X)
|
||||
|
||||
TEST_CASE("ppc64: addi", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
|
||||
ctx.ADDI(powah::R2, powah::R2, 0);
|
||||
ctx.ADDIS(powah::R2, powah::R12, 0);
|
||||
REQUIRE(data[0] == EB32(0x00004238));
|
||||
REQUIRE(data[1] == EB32(0x00004c3c));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: std/mr", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
|
||||
ctx.STD(powah::R26, powah::R1, 144);
|
||||
ctx.MR(powah::R26, powah::R4);
|
||||
ctx.STD(powah::R30, powah::R1, 176);
|
||||
ctx.MR(powah::R30, powah::R3);
|
||||
ctx.RLDICR(powah::R4, powah::R5, 25, 6);
|
||||
ctx.STD(powah::R28, powah::R1, 160);
|
||||
REQUIRE(data[0] == EB32(0x900041fb));
|
||||
REQUIRE(data[1] == EB32(0x78239a7c));
|
||||
REQUIRE(data[2] == EB32(0xb000c1fb));
|
||||
REQUIRE(data[3] == EB32(0x781b7e7c));
|
||||
REQUIRE(data[4] == EB32(0x84c9a478));
|
||||
REQUIRE(data[5] == EB32(0xa00081fb));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: sldi", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
|
||||
ctx.SLDI(powah::R3, powah::R5, 37);
|
||||
REQUIRE(data[0] == EB32(0x862ea378));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: rldicr", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
ctx.RLDICR(powah::R1, powah::R1, 0, 0);
|
||||
ctx.RLDICR(powah::R1, powah::R1, 1, 0);
|
||||
ctx.RLDICR(powah::R1, powah::R1, 0, 1);
|
||||
ctx.RLDICR(powah::R1, powah::R1, 1, 1);
|
||||
ctx.RLDICR(powah::R1, powah::R1, 31, 31);
|
||||
REQUIRE(data[0] == EB32(0x04002178));
|
||||
REQUIRE(data[1] == EB32(0x04082178));
|
||||
REQUIRE(data[2] == EB32(0x44002178));
|
||||
REQUIRE(data[3] == EB32(0x44082178));
|
||||
REQUIRE(data[4] == EB32(0xc4ff2178));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: mr/or/std", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
ctx.MR(powah::R27, powah::R7);
|
||||
ctx.MR(powah::R29, powah::R6);
|
||||
ctx.OR(powah::R3, powah::R3, powah::R4);
|
||||
ctx.MR(powah::R4, powah::R28);
|
||||
ctx.CRMOVE(powah::CPR{8}, powah::CPR{1});
|
||||
ctx.MR(powah::R25, powah::R5);
|
||||
ctx.OR(powah::R3, powah::R3, powah::R26);
|
||||
ctx.STD(powah::R3, powah::R1, 56);
|
||||
ctx.MR(powah::R3, powah::R30);
|
||||
REQUIRE(data[0] == EB32(0x783bfb7c));
|
||||
REQUIRE(data[1] == EB32(0x7833dd7c));
|
||||
REQUIRE(data[2] == EB32(0x7823637c));
|
||||
REQUIRE(data[3] == EB32(0x78e3847f));
|
||||
REQUIRE(data[4] == EB32(0x820b014d));
|
||||
REQUIRE(data[5] == EB32(0x782bb97c));
|
||||
REQUIRE(data[6] == EB32(0x78d3637c));
|
||||
REQUIRE(data[7] == EB32(0x380061f8));
|
||||
REQUIRE(data[8] == EB32(0x78f3c37f));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
ctx.LD(powah::R4, powah::R1, 72);
|
||||
ctx.LWZ(powah::R5, powah::R1, 80);
|
||||
ctx.CRAND(powah::CPR{20}, powah::CPR{10}, powah::CPR{9});
|
||||
ctx.ADDI(powah::R6, powah::R4, 4);
|
||||
ctx.ANDIS_(powah::R4, powah::R5, 1992);
|
||||
ctx.LD(powah::R5, powah::R30, 1984);
|
||||
ctx.LBZ(powah::R3, powah::R1, 84);
|
||||
ctx.CLRLDI(powah::R26, powah::R6, 8);
|
||||
ctx.STW(powah::R4, powah::R1, 80);
|
||||
ctx.ADDI(powah::R5, powah::R5, 1);
|
||||
ctx.STD(powah::R26, powah::R1, 72);
|
||||
ctx.STD(powah::R5, powah::R30, 1984);
|
||||
REQUIRE(data[0] == EB32(0x480081e8));
|
||||
REQUIRE(data[1] == EB32(0x5000a180));
|
||||
REQUIRE(data[2] == EB32(0x024a8a4e));
|
||||
REQUIRE(data[3] == EB32(0x0400c438));
|
||||
REQUIRE(data[4] == EB32(0xc807a474));
|
||||
REQUIRE(data[5] == EB32(0xc007bee8));
|
||||
REQUIRE(data[6] == EB32(0x54006188));
|
||||
REQUIRE(data[7] == EB32(0x0002da78));
|
||||
REQUIRE(data[8] == EB32(0x50008190));
|
||||
REQUIRE(data[9] == EB32(0x0100a538));
|
||||
REQUIRE(data[10] == EB32(0x480041fb));
|
||||
REQUIRE(data[11] == EB32(0xc007bef8));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: rotldi", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
ctx.ROTLDI(powah::R5, powah::R3, 16);
|
||||
ctx.ROTLDI(powah::R4, powah::R3, 8);
|
||||
ctx.RLDIMI(powah::R4, powah::R5, 8, 48);
|
||||
ctx.ROTLDI(powah::R5, powah::R3, 24);
|
||||
ctx.RLDIMI(powah::R4, powah::R5, 16, 40);
|
||||
ctx.ROTLDI(powah::R5, powah::R3, 32);
|
||||
ctx.RLDIMI(powah::R4, powah::R5, 24, 32);
|
||||
ctx.ROTLDI(powah::R5, powah::R3, 48);
|
||||
ctx.RLDIMI(powah::R4, powah::R5, 40, 16);
|
||||
ctx.ROTLDI(powah::R5, powah::R3, 56);
|
||||
ctx.RLDIMI(powah::R4, powah::R5, 48, 8);
|
||||
ctx.RLDIMI(powah::R4, powah::R3, 56, 0);
|
||||
ctx.MR(powah::R3, powah::R4);
|
||||
REQUIRE(data[0] == EB32(0x00806578));
|
||||
REQUIRE(data[1] == EB32(0x00406478));
|
||||
REQUIRE(data[2] == EB32(0x2c44a478));
|
||||
REQUIRE(data[3] == EB32(0x00c06578));
|
||||
REQUIRE(data[4] == EB32(0x2c82a478));
|
||||
REQUIRE(data[5] == EB32(0x02006578));
|
||||
REQUIRE(data[6] == EB32(0x2cc0a478));
|
||||
REQUIRE(data[7] == EB32(0x02806578));
|
||||
REQUIRE(data[8] == EB32(0x0e44a478));
|
||||
REQUIRE(data[9] == EB32(0x02c06578));
|
||||
REQUIRE(data[10] == EB32(0x0e82a478));
|
||||
REQUIRE(data[11] == EB32(0x0ec06478));
|
||||
REQUIRE(data[12] == EB32(0x7823837c));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: branch-backwards", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
powah::Label l_3 = ctx.DefineLabel();
|
||||
ctx.LABEL(l_3);
|
||||
ctx.ADD(powah::R1, powah::R2, powah::R3);
|
||||
ctx.B(l_3);
|
||||
ctx.ApplyRelocs();
|
||||
REQUIRE(data[0] == EB32(0x141a227c));
|
||||
REQUIRE(data[1] == EB32(0xfcffff4b));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: rlwimi madness", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
ctx.ROTLWI(powah::R10, powah::R3, 24);
|
||||
ctx.SRDI(powah::R9, powah::R3, 32);
|
||||
ctx.RLWIMI(powah::R10, powah::R3, 8, 8, 15);
|
||||
ctx.RLWIMI(powah::R10, powah::R3, 8, 24, 31);
|
||||
ctx.ROTLWI(powah::R3, powah::R9, 24);
|
||||
ctx.RLWIMI(powah::R3, powah::R9, 8, 8, 15);
|
||||
ctx.RLWIMI(powah::R3, powah::R9, 8, 24, 31);
|
||||
ctx.RLDIMI(powah::R3, powah::R10, 32, 0);
|
||||
REQUIRE(data[0] == EB32(0x3ec06a54));
|
||||
REQUIRE(data[1] == EB32(0x22006978));
|
||||
REQUIRE(data[2] == EB32(0x1e426a50));
|
||||
REQUIRE(data[3] == EB32(0x3e466a50));
|
||||
REQUIRE(data[4] == EB32(0x3ec02355));
|
||||
REQUIRE(data[5] == EB32(0x1e422351));
|
||||
REQUIRE(data[6] == EB32(0x3e462351));
|
||||
REQUIRE(data[7] == EB32(0x0e004379));
|
||||
}
|
||||
|
||||
/*
|
||||
0: 78 1b 68 7c mr 8, 3
|
||||
4: 38 28 83 7c and 3, 4, 5
|
||||
8: 74 00 6a 7c cntlzd 10, 3
|
||||
c: 76 06 69 7c sradi 9, 3, 32
|
||||
10: 82 d1 4a 79 rldicl 10, 10, 58, 6
|
||||
14: 00 00 29 55 rlwinm 9, 9, 0, 0, 0
|
||||
18: 64 f0 4a 79 sldi 10, 10, 30
|
||||
1c: 78 53 29 7d or 9, 9, 10
|
||||
20: 00 00 28 f9 std 9, 0(8)
|
||||
24: 20 00 80 4e blr
|
||||
*/
|
||||
TEST_CASE("ppc64: functor-2", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
ctx.MR(powah::R8, powah::R3);
|
||||
ctx.AND(powah::R3, powah::R4, powah::R5);
|
||||
ctx.CNTLZD(powah::R10, powah::R3);
|
||||
ctx.SRADI(powah::R9, powah::R3, 32);
|
||||
ctx.RLDICL(powah::R10, powah::R10, 58, 6);
|
||||
ctx.RLWINM(powah::R9, powah::R9, 0, 0, 0);
|
||||
ctx.SLDI(powah::R10, powah::R10, 30);
|
||||
ctx.OR(powah::R9, powah::R9, powah::R10);
|
||||
ctx.STD(powah::R9, powah::R8, 0);
|
||||
ctx.BLR();
|
||||
REQUIRE(data[0] == EB32(0x781b687c));
|
||||
REQUIRE(data[1] == EB32(0x3828837c));
|
||||
REQUIRE(data[2] == EB32(0x74006a7c));
|
||||
REQUIRE(data[3] == EB32(0x7606697c));
|
||||
REQUIRE(data[4] == EB32(0x82d14a79));
|
||||
REQUIRE(data[5] == EB32(0x00002955));
|
||||
REQUIRE(data[6] == EB32(0x64f04a79));
|
||||
REQUIRE(data[7] == EB32(0x7853297d));
|
||||
REQUIRE(data[8] == EB32(0x000028f9));
|
||||
REQUIRE(data[9] == EB32(0x2000804e));
|
||||
}
|
||||
|
||||
TEST_CASE("ppc64: functor-1", "[ppc64]") {
|
||||
std::vector<uint32_t> data(64);
|
||||
powah::Context ctx(data.data(), data.size());
|
||||
powah::Label l_4 = ctx.DefineLabel();
|
||||
powah::Label l_7 = ctx.DefineLabel();
|
||||
ctx.CMPLD(powah::CR0, powah::R3, powah::R4);
|
||||
ctx.MR(powah::R9, powah::R3);
|
||||
ctx.BGT(powah::CR0, l_7);
|
||||
ctx.CMPLDI(powah::CR0, powah::R3, 3781);
|
||||
ctx.LI(powah::R3, 1);
|
||||
ctx.BGTLR(powah::CR0);
|
||||
ctx.CMPLD(powah::CR0, powah::R9, powah::R5);
|
||||
ctx.BLE(powah::CR0, l_4);
|
||||
ctx.SUBF(powah::R5, powah::R9, powah::R5);
|
||||
ctx.XOR(powah::R3, powah::R5, powah::R4);
|
||||
ctx.BLR();
|
||||
ctx.LABEL(l_4);
|
||||
ctx.ADD(powah::R5, powah::R4, powah::R5);
|
||||
ctx.ADD(powah::R3, powah::R5, powah::R9);
|
||||
ctx.BLR();
|
||||
ctx.LABEL(l_7);
|
||||
ctx.ADD(powah::R3, powah::R4, powah::R5);
|
||||
ctx.BLR();
|
||||
ctx.ApplyRelocs();
|
||||
REQUIRE(data[0] == EB32(0x4020237c));
|
||||
REQUIRE(data[1] == EB32(0x781b697c));
|
||||
REQUIRE(data[2] == EB32(0x30008141));
|
||||
REQUIRE(data[3] == EB32(0xc50e2328));
|
||||
REQUIRE(data[4] == EB32(0x01006038));
|
||||
REQUIRE(data[5] == EB32(0x2000814d));
|
||||
REQUIRE(data[6] == EB32(0x4028297c));
|
||||
REQUIRE(data[7] == EB32(0x10008140));
|
||||
REQUIRE(data[8] == EB32(0x5028a97c));
|
||||
REQUIRE(data[9] == EB32(0x7822a37c));
|
||||
REQUIRE(data[10] == EB32(0x2000804e));
|
||||
REQUIRE(data[11] == EB32(0x142aa47c));
|
||||
REQUIRE(data[12] == EB32(0x144a657c));
|
||||
REQUIRE(data[13] == EB32(0x2000804e));
|
||||
REQUIRE(data[14] == EB32(0x142a647c));
|
||||
REQUIRE(data[15] == EB32(0x2000804e));
|
||||
}
|
||||
|
||||
#if defined(ARCHITECTURE_powerpc64)
|
||||
/*
|
||||
0: d619637c mullw 3, 3, 3
|
||||
4: 20006378 clrldi 3, 3, 32
|
||||
8: 2000804e blr
|
||||
*/
|
||||
TEST_CASE("ppc64: live-exec square", "[ppc64]") {
|
||||
uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
REQUIRE(data != nullptr);
|
||||
|
||||
powah::Context ctx((void*)data, 4096);
|
||||
ctx.MULLW(powah::R3, powah::R3, powah::R3);
|
||||
ctx.CLRLDI(powah::R3, powah::R3, 32);
|
||||
ctx.BLR();
|
||||
REQUIRE(data[0] == EB32(0xd619637c));
|
||||
REQUIRE(data[1] == EB32(0x20006378));
|
||||
REQUIRE(data[2] == EB32(0x2000804e));
|
||||
|
||||
auto* fn = (int (*)(int))data;
|
||||
REQUIRE(fn(4) == 4 * 4);
|
||||
REQUIRE(fn(8) == 8 * 8);
|
||||
|
||||
munmap((void*)data, 4096);
|
||||
}
|
||||
|
||||
/*
|
||||
int f(int a, int b, int c) {
|
||||
a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c;
|
||||
return a * a + b ^ c & b;
|
||||
}
|
||||
*/
|
||||
TEST_CASE("ppc64: live-exec xoralu", "[ppc64]") {
|
||||
uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
REQUIRE(data != nullptr);
|
||||
|
||||
powah::Context ctx((void*)data, 4096);
|
||||
powah::Label l_2 = ctx.DefineLabel();
|
||||
powah::Label l_3 = ctx.DefineLabel();
|
||||
ctx.CMPW(powah::R3, powah::R4);
|
||||
ctx.BGT(powah::CR0, l_2);
|
||||
ctx.ADDI(powah::R6, powah::R5, 402);
|
||||
ctx.B(l_3);
|
||||
ctx.LABEL(l_2);
|
||||
ctx.ADDI(powah::R6, powah::R4, 1);
|
||||
ctx.ADDIS(powah::R6, powah::R6, -1);
|
||||
ctx.LABEL(l_3);
|
||||
ctx.ADDI(powah::R4, powah::R4, 2);
|
||||
ctx.ADD(powah::R3, powah::R6, powah::R3);
|
||||
ctx.MULLW(powah::R6, powah::R4, powah::R5);
|
||||
ctx.MULLW(powah::R3, powah::R3, powah::R3);
|
||||
ctx.AND(powah::R5, powah::R5, powah::R6);
|
||||
ctx.ADD(powah::R3, powah::R3, powah::R4);
|
||||
ctx.AND(powah::R4, powah::R5, powah::R4);
|
||||
ctx.XOR(powah::R3, powah::R3, powah::R4);
|
||||
ctx.EXTSW(powah::R3, powah::R3);
|
||||
ctx.BLR();
|
||||
ctx.ApplyRelocs();
|
||||
REQUIRE(data[0] == EB32(0x0020037c));
|
||||
REQUIRE(data[1] == EB32(0x0c008141));
|
||||
REQUIRE(data[2] == EB32(0x9201c538));
|
||||
REQUIRE(data[3] == EB32(0x0c000048));
|
||||
REQUIRE(data[4] == EB32(0x0100c438));
|
||||
REQUIRE(data[5] == EB32(0xffffc63c));
|
||||
REQUIRE(data[6] == EB32(0x02008438));
|
||||
REQUIRE(data[7] == EB32(0x141a667c));
|
||||
REQUIRE(data[8] == EB32(0xd629c47c));
|
||||
REQUIRE(data[9] == EB32(0xd619637c));
|
||||
REQUIRE(data[10] == EB32(0x3830a57c));
|
||||
REQUIRE(data[11] == EB32(0x1422637c));
|
||||
REQUIRE(data[12] == EB32(0x3820a47c));
|
||||
REQUIRE(data[13] == EB32(0x7822637c));
|
||||
REQUIRE(data[14] == EB32(0xb407637c));
|
||||
REQUIRE(data[15] == EB32(0x2000804e));
|
||||
|
||||
auto const orig = [](int a, int b, int c) {
|
||||
a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c;
|
||||
return a * a + b ^ c & b;
|
||||
};
|
||||
auto* fn = (int (*)(int, int, int))data;
|
||||
REQUIRE(fn(0, 1, 2) == orig(0, 1, 2));
|
||||
REQUIRE(fn(6456, 4564, 4564561) == orig(6456, 4564, 4564561));
|
||||
|
||||
munmap((void*)data, 4096);
|
||||
}
|
||||
#endif
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
include_directories(.)
|
||||
|
||||
# Dynarmic
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM)
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_powerpc64) AND NOT YUZU_STATIC_ROOM)
|
||||
add_subdirectory(dynarmic)
|
||||
add_library(dynarmic::dynarmic ALIAS dynarmic)
|
||||
endif()
|
||||
|
||||
@@ -539,40 +539,6 @@ object NativeLibrary {
|
||||
*/
|
||||
external fun installKeys(path: String, ext: String): Int
|
||||
|
||||
/**
|
||||
* @return Whether this GPU can run the Lossless Scaling frame generation shaders,
|
||||
* which are built against the Vulkan memory model.
|
||||
*/
|
||||
external fun supportsFrameGeneration(): Boolean
|
||||
|
||||
/**
|
||||
* @return Path the user-supplied Lossless Scaling library is expected at.
|
||||
*/
|
||||
external fun getLosslessDllPath(): String
|
||||
|
||||
/**
|
||||
* Parses the installed Lossless Scaling library and checks that every shader the
|
||||
* frame generation chain needs is present.
|
||||
*
|
||||
* @return The result code, matching the losslessDllResults array.
|
||||
*/
|
||||
external fun validateLosslessDll(): Int
|
||||
|
||||
/**
|
||||
* Translates the frame generation shaders out of the installed Lossless Scaling library
|
||||
* and writes them to the SPIR-V cache. Slow, so call it off the main thread.
|
||||
*
|
||||
* @return The result code, matching the losslessDllResults array.
|
||||
*/
|
||||
external fun prepareLosslessDll(): Int
|
||||
|
||||
/**
|
||||
* Deletes the installed Lossless Scaling library.
|
||||
*
|
||||
* @return Whether the library is gone after the call.
|
||||
*/
|
||||
external fun removeLosslessDll(): Boolean
|
||||
|
||||
/**
|
||||
* Checks the PatchManager for any addons that are available
|
||||
*
|
||||
|
||||
@@ -559,15 +559,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||
private fun enableFullscreenImmersive() {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
window.decorView.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
|
||||
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
||||
controller.hide(WindowInsetsCompat.Type.systemBars())
|
||||
controller.systemBarsBehavior =
|
||||
|
||||
-4
@@ -37,10 +37,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
|
||||
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
|
||||
RENDERER_SAMPLE_SHADING("sample_shading"),
|
||||
RENDERER_FRAME_GEN("frame_gen"),
|
||||
RENDERER_FRAME_GEN_FP16("frame_gen_fp16"),
|
||||
RENDERER_FRAME_GEN_FLOW_SCALE_AUTO("frame_gen_flow_scale_auto"),
|
||||
RENDERER_FRAME_GEN_DUMP_FLOW("frame_gen_dump_flow"),
|
||||
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
|
||||
PICTURE_IN_PICTURE("picture_in_picture"),
|
||||
USE_CUSTOM_RTC("custom_rtc_enabled"),
|
||||
|
||||
@@ -19,10 +19,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
||||
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
|
||||
RENDERER_ACCURACY("gpu_accuracy"),
|
||||
RENDERER_RESOLUTION("resolution_setup"),
|
||||
RENDERER_FRAME_GEN_MULTIPLIER("frame_gen_multiplier"),
|
||||
RENDERER_FRAME_GEN_TARGET_RATE("frame_gen_target_rate"),
|
||||
RENDERER_FRAME_GEN_QUEUE_TARGET("frame_gen_queue_target"),
|
||||
RENDERER_FRAME_GEN_FLOW_SCALE("frame_gen_flow_scale"),
|
||||
RENDERER_VSYNC("use_vsync"),
|
||||
RENDERER_SCALING_FILTER("scaling_filter"),
|
||||
RENDERER_ANTI_ALIASING("anti_aliasing"),
|
||||
|
||||
@@ -11,7 +11,6 @@ object Settings {
|
||||
SECTION_ROOT(R.string.advanced_settings),
|
||||
SECTION_SYSTEM(R.string.preferences_system),
|
||||
SECTION_RENDERER(R.string.preferences_graphics),
|
||||
SECTION_FRAME_GEN(R.string.frame_gen),
|
||||
SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options),
|
||||
SECTION_INPUT_OVERLAY(R.string.input_overlay_options),
|
||||
SECTION_SOC_OVERLAY(R.string.soc_overlay_options),
|
||||
|
||||
-104
@@ -21,7 +21,6 @@ import org.yuzu.yuzu_emu.features.settings.model.LongSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
import org.yuzu.yuzu_emu.network.NetDataValidators
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
|
||||
/**
|
||||
@@ -66,19 +65,6 @@ abstract class SettingsItem(
|
||||
return NativeLibrary.isFirmwareAvailable()
|
||||
}
|
||||
|
||||
if (setting.key in frameGenKeys &&
|
||||
!(LosslessScalingHelper.isInstalled() && LosslessScalingHelper.isSupportedByGpu())
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
// A frame rate target moves the multiplier on its own
|
||||
if (setting.key == IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key &&
|
||||
frameGenTargetRate != 0
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Can't edit settings that aren't saveable in per-game config even if they are switchable
|
||||
if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
|
||||
return false
|
||||
@@ -102,31 +88,7 @@ abstract class SettingsItem(
|
||||
val clearable: Boolean
|
||||
get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
|
||||
|
||||
private val frameGenTargetRate: Int
|
||||
get() {
|
||||
val key = IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key
|
||||
val needsGlobal = if (NativeLibrary.isRunning() &&
|
||||
!NativeConfig.isPerGameConfigLoaded()
|
||||
) {
|
||||
!NativeConfig.usingGlobal(key)
|
||||
} else {
|
||||
NativeConfig.usingGlobal(key)
|
||||
}
|
||||
return IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.getInt(needsGlobal)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val frameGenKeys = setOf(
|
||||
BooleanSetting.RENDERER_FRAME_GEN.key,
|
||||
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key,
|
||||
IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key,
|
||||
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key,
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key,
|
||||
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key,
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FP16.key,
|
||||
BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW.key
|
||||
)
|
||||
|
||||
const val TYPE_HEADER = 0
|
||||
const val TYPE_SWITCH = 1
|
||||
const val TYPE_SINGLE_CHOICE = 2
|
||||
@@ -624,7 +586,6 @@ abstract class SettingsItem(
|
||||
IntSetting.FSR_SHARPENING_SLIDER,
|
||||
titleId = R.string.fsr_sharpness,
|
||||
descriptionId = R.string.fsr_sharpness_description,
|
||||
max = 200,
|
||||
units = "%"
|
||||
)
|
||||
)
|
||||
@@ -646,71 +607,6 @@ abstract class SettingsItem(
|
||||
valuesId = R.array.rendererAntiAliasingValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN,
|
||||
titleId = R.string.frame_gen,
|
||||
descriptionId = R.string.frame_gen_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER,
|
||||
titleId = R.string.frame_gen_multiplier,
|
||||
descriptionId = R.string.frame_gen_multiplier_description,
|
||||
choicesId = R.array.frameGenMultiplierNames,
|
||||
valuesId = R.array.frameGenMultiplierValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_FRAME_GEN_TARGET_RATE,
|
||||
titleId = R.string.frame_gen_target_rate,
|
||||
descriptionId = R.string.frame_gen_target_rate_description,
|
||||
choicesId = R.array.frameGenTargetRateNames,
|
||||
valuesId = R.array.frameGenTargetRateValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET,
|
||||
titleId = R.string.frame_gen_queue_target,
|
||||
descriptionId = R.string.frame_gen_queue_target_description,
|
||||
choicesId = R.array.frameGenQueueTargetNames,
|
||||
valuesId = R.array.frameGenQueueTargetValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO,
|
||||
titleId = R.string.frame_gen_flow_scale_auto,
|
||||
descriptionId = R.string.frame_gen_flow_scale_auto_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SliderSetting(
|
||||
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE,
|
||||
titleId = R.string.frame_gen_flow_scale,
|
||||
descriptionId = R.string.frame_gen_flow_scale_description,
|
||||
min = 25,
|
||||
max = 100,
|
||||
units = "%"
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN_FP16,
|
||||
titleId = R.string.frame_gen_fp16,
|
||||
descriptionId = R.string.frame_gen_fp16_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW,
|
||||
titleId = R.string.frame_gen_dump_flow,
|
||||
descriptionId = R.string.frame_gen_dump_flow_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_SCREEN_LAYOUT,
|
||||
|
||||
+1
-3
@@ -382,9 +382,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
|
||||
}
|
||||
scSetting.setSelectedValue(value)
|
||||
|
||||
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key ||
|
||||
scSetting.setting.key == IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key
|
||||
) {
|
||||
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key) {
|
||||
settingsViewModel.setShouldReloadSettingsList(true)
|
||||
}
|
||||
|
||||
|
||||
+3
-44
@@ -27,7 +27,6 @@ import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.*
|
||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.FullscreenHelper
|
||||
@@ -77,46 +76,6 @@ class SettingsFragmentPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFrameGenSettings(sl: ArrayList<SettingsItem>) {
|
||||
sl.apply {
|
||||
if (!LosslessScalingHelper.isSupportedByGpu()) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = R.string.frame_gen_unsupported,
|
||||
descriptionId = R.string.frame_gen_unsupported_description,
|
||||
isRunnable = false
|
||||
) {}
|
||||
)
|
||||
} else if (!LosslessScalingHelper.isInstalled()) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = R.string.lossless_scaling_missing,
|
||||
descriptionId = R.string.lossless_scaling_missing_description,
|
||||
isRunnable = false
|
||||
) {}
|
||||
)
|
||||
}
|
||||
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN.key)
|
||||
add(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
|
||||
if (IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.getInt(
|
||||
getNeedsGlobalForKey(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
|
||||
) == 0
|
||||
) {
|
||||
add(IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key)
|
||||
}
|
||||
add(IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key)
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
|
||||
if (!BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.getBoolean(
|
||||
getNeedsGlobalForKey(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
|
||||
)
|
||||
) {
|
||||
add(IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key)
|
||||
}
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN_FP16.key)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSharpnessScalingFilterSelected(): Boolean {
|
||||
val needsGlobal = getNeedsGlobalForKey(IntSetting.RENDERER_SCALING_FILTER.key)
|
||||
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal)
|
||||
@@ -161,7 +120,6 @@ class SettingsFragmentPresenter(
|
||||
MenuTag.SECTION_ROOT -> addConfigSettings(sl)
|
||||
MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
|
||||
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
||||
MenuTag.SECTION_FRAME_GEN -> addFrameGenSettings(sl)
|
||||
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
|
||||
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
|
||||
MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl)
|
||||
@@ -312,6 +270,8 @@ class SettingsFragmentPresenter(
|
||||
// TODO(crueter): sub-submenus?
|
||||
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
|
||||
sl.apply {
|
||||
// add(IntSetting.RENDERER_NVDEC_EMULATION.key)
|
||||
|
||||
add(IntSetting.RENDERER_RESOLUTION.key)
|
||||
add(IntSetting.RENDERER_VSYNC.key)
|
||||
add(IntSetting.RENDERER_SCALING_FILTER.key)
|
||||
@@ -328,7 +288,6 @@ class SettingsFragmentPresenter(
|
||||
add(IntSetting.MAX_ANISOTROPY.key)
|
||||
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
|
||||
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
|
||||
add(IntSetting.RENDERER_NVDEC_EMULATION.key)
|
||||
|
||||
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
|
||||
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
|
||||
@@ -343,6 +302,7 @@ class SettingsFragmentPresenter(
|
||||
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
|
||||
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
|
||||
add(BooleanSetting.EMULATE_BGR565.key)
|
||||
add(BooleanSetting.RESCALE_HACK.key)
|
||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
||||
add(IntSetting.ANDROID_PIPELINE_WORKERS.key)
|
||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key)
|
||||
@@ -1336,7 +1296,6 @@ class SettingsFragmentPresenter(
|
||||
add(BooleanSetting.DUMP_GUEST_SHADERS.key)
|
||||
add(BooleanSetting.GPU_LOG_SHADER_DUMPS.key)
|
||||
add(BooleanSetting.DUMP_MACROS.key)
|
||||
add(BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW.key)
|
||||
add(BooleanSetting.GPU_LOG_MEMORY_TRACKING.key)
|
||||
add(BooleanSetting.GPU_LOG_DRIVER_DEBUG.key)
|
||||
add(IntSetting.GPU_LOG_RING_BUFFER_SIZE.key)
|
||||
|
||||
-2
@@ -29,7 +29,6 @@ enum class SettingsSubscreen {
|
||||
DRIVER_MANAGER,
|
||||
DRIVER_FETCHER,
|
||||
FREEDRENO_SETTINGS,
|
||||
LOSSLESS_MANAGER,
|
||||
APPLET_LAUNCHER,
|
||||
INSTALLABLE,
|
||||
GAME_FOLDERS,
|
||||
@@ -127,7 +126,6 @@ class SettingsSubscreenActivity : AppCompatActivity() {
|
||||
SettingsSubscreen.DRIVER_MANAGER -> R.id.driverManagerFragment
|
||||
SettingsSubscreen.DRIVER_FETCHER -> R.id.driverFetcherFragment
|
||||
SettingsSubscreen.FREEDRENO_SETTINGS -> R.id.freedrenoSettingsFragment
|
||||
SettingsSubscreen.LOSSLESS_MANAGER -> R.id.losslessManagerFragment
|
||||
SettingsSubscreen.APPLET_LAUNCHER -> R.id.appletLauncherFragment
|
||||
SettingsSubscreen.INSTALLABLE -> R.id.installableFragment
|
||||
SettingsSubscreen.GAME_FOLDERS -> R.id.gameFoldersFragment
|
||||
|
||||
@@ -1182,7 +1182,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
container,
|
||||
IntSetting.FSR_SHARPENING_SLIDER,
|
||||
minValue = 0,
|
||||
maxValue = 200,
|
||||
maxValue = 100,
|
||||
units = "%"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -369,21 +369,6 @@ class GamePropertiesFragment : Fragment() {
|
||||
)
|
||||
)
|
||||
}
|
||||
add(
|
||||
SubmenuProperty(
|
||||
R.string.frame_gen,
|
||||
R.string.frame_gen_per_game_description,
|
||||
R.drawable.ic_duck,
|
||||
action = {
|
||||
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
|
||||
args.game,
|
||||
Settings.MenuTag.SECTION_FRAME_GEN
|
||||
)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
if (GpuDriverHelper.isAdrenoGpu()) {
|
||||
add(
|
||||
SubmenuProperty(
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||
|
||||
class HomeSettingsFragment : Fragment() {
|
||||
@@ -171,24 +170,6 @@ class HomeSettingsFragment : Fragment() {
|
||||
)
|
||||
)
|
||||
}
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.lossless_scaling,
|
||||
R.string.lossless_scaling_description,
|
||||
R.drawable.ic_duck,
|
||||
{
|
||||
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
|
||||
SettingsSubscreen.LOSSLESS_MANAGER,
|
||||
null
|
||||
)
|
||||
binding.root.findNavController().navigate(action)
|
||||
},
|
||||
{ true },
|
||||
0,
|
||||
0,
|
||||
LosslessScalingHelper.statusText
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.multiplayer,
|
||||
@@ -356,7 +337,6 @@ class HomeSettingsFragment : Fragment() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
driverViewModel.updateDriverNameForGame(null)
|
||||
LosslessScalingHelper.refreshStatus()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentLosslessManagerBinding
|
||||
import org.yuzu.yuzu_emu.features.fetcher.SpacingItemDecoration
|
||||
import org.yuzu.yuzu_emu.model.HomeSetting
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||
import org.yuzu.yuzu_emu.utils.collect
|
||||
|
||||
class LosslessManagerFragment : Fragment() {
|
||||
private var _binding: FragmentLosslessManagerBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentLosslessManagerBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.toolbarLossless.setNavigationOnClickListener {
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
binding.losslessOptionsList.apply {
|
||||
layoutManager =
|
||||
GridLayoutManager(requireContext(), resources.getInteger(R.integer.grid_columns))
|
||||
addItemDecoration(
|
||||
SpacingItemDecoration(resources.getDimensionPixelSize(R.dimen.spacing_small))
|
||||
)
|
||||
}
|
||||
|
||||
LosslessScalingHelper.statusText.collect(viewLifecycleOwner) { refreshOptions() }
|
||||
|
||||
setInsets()
|
||||
}
|
||||
|
||||
private fun refreshOptions() {
|
||||
binding.losslessOptionsList.adapter = HomeSettingAdapter(
|
||||
requireActivity() as AppCompatActivity,
|
||||
viewLifecycleOwner,
|
||||
buildOptions()
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildOptions(): List<HomeSetting> {
|
||||
val installed = LosslessScalingHelper.isInstalled()
|
||||
return listOf(
|
||||
HomeSetting(
|
||||
if (installed) R.string.lossless_scaling_replace else R.string.lossless_scaling_install,
|
||||
if (installed) {
|
||||
R.string.lossless_scaling_replace_description
|
||||
} else {
|
||||
R.string.lossless_scaling_install_description
|
||||
},
|
||||
R.drawable.ic_install,
|
||||
{ dllPickerLauncher.launch(arrayOf("*/*")) },
|
||||
{ !NativeLibrary.isRunning() },
|
||||
R.string.lossless_scaling_locked,
|
||||
R.string.lossless_scaling_locked_description,
|
||||
LosslessScalingHelper.statusText
|
||||
),
|
||||
HomeSetting(
|
||||
R.string.lossless_scaling_remove,
|
||||
R.string.lossless_scaling_remove_description,
|
||||
R.drawable.ic_delete,
|
||||
{ confirmRemoval() },
|
||||
{ installed && !NativeLibrary.isRunning() },
|
||||
if (installed) {
|
||||
R.string.lossless_scaling_locked
|
||||
} else {
|
||||
R.string.lossless_scaling_remove_unavailable
|
||||
},
|
||||
if (installed) {
|
||||
R.string.lossless_scaling_locked_description
|
||||
} else {
|
||||
R.string.lossless_scaling_remove_unavailable_description
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun confirmRemoval() {
|
||||
MessageDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
titleId = R.string.lossless_scaling_remove,
|
||||
descriptionId = R.string.lossless_scaling_remove_confirmation,
|
||||
positiveButtonTitleId = R.string.lossless_scaling_remove,
|
||||
positiveAction = { LosslessScalingHelper.remove() },
|
||||
showNegativeButton = true,
|
||||
negativeAction = {}
|
||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
|
||||
private val dllPickerLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val resultStrings = resources.getStringArray(R.array.losslessDllResults)
|
||||
ProgressDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
R.string.lossless_scaling_installing,
|
||||
false
|
||||
) { _, _ ->
|
||||
val installResult = LosslessScalingHelper.install(result)
|
||||
if (installResult == LosslessScalingHelper.RESULT_OK) {
|
||||
getString(R.string.lossless_scaling_install_success)
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
titleId = R.string.lossless_scaling_install_failed,
|
||||
descriptionString = resultStrings[installResult]
|
||||
)
|
||||
}
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
|
||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
|
||||
binding.appbarLossless.updateMargins(
|
||||
left = barInsets.left + cutoutInsets.left,
|
||||
right = barInsets.right + cutoutInsets.right
|
||||
)
|
||||
|
||||
binding.scrollViewLossless.updatePadding(bottom = barInsets.bottom)
|
||||
|
||||
binding.losslessOptionsList.updatePadding(
|
||||
left = barInsets.left + cutoutInsets.left,
|
||||
right = barInsets.right + cutoutInsets.right
|
||||
)
|
||||
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
@@ -42,7 +42,6 @@ import org.yuzu.yuzu_emu.model.SetupPage
|
||||
import org.yuzu.yuzu_emu.model.PageState
|
||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||
@@ -203,24 +202,6 @@ class SetupFragment : Fragment() {
|
||||
R.string.install_firmware_warning_help,
|
||||
)
|
||||
)
|
||||
add(
|
||||
PageButton(
|
||||
R.drawable.ic_duck,
|
||||
R.string.lossless_scaling,
|
||||
R.string.lossless_scaling_setup_description,
|
||||
{
|
||||
pageButtonCallback = it
|
||||
getLosslessDll.launch(arrayOf("*/*"))
|
||||
},
|
||||
{
|
||||
if (LosslessScalingHelper.isInstalled()) {
|
||||
ButtonState.BUTTON_ACTION_COMPLETE
|
||||
} else {
|
||||
ButtonState.BUTTON_ACTION_INCOMPLETE
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
PageButton(
|
||||
R.drawable.ic_controller,
|
||||
@@ -465,32 +446,6 @@ class SetupFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
val getLosslessDll =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val resultStrings = resources.getStringArray(R.array.losslessDllResults)
|
||||
ProgressDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
R.string.lossless_scaling_installing,
|
||||
false
|
||||
) { _, _ ->
|
||||
val installResult = LosslessScalingHelper.install(result)
|
||||
if (installResult == LosslessScalingHelper.RESULT_OK) {
|
||||
getString(R.string.lossless_scaling_install_success)
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
titleId = R.string.lossless_scaling_install_failed,
|
||||
descriptionString = resultStrings[installResult]
|
||||
)
|
||||
}
|
||||
}.apply {
|
||||
onDialogComplete = { checkForButtonState.invoke() }
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
val getGamesDirectory =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||
if (result != null) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user