aboutsummaryrefslogtreecommitdiff
path: root/docs/dynarmic
diff options
context:
space:
mode:
Diffstat (limited to 'docs/dynarmic')
-rw-r--r--docs/dynarmic/Design.md84
-rw-r--r--docs/dynarmic/README.md323
2 files changed, 51 insertions, 356 deletions
diff --git a/docs/dynarmic/Design.md b/docs/dynarmic/Design.md
index 020cfd65bd..77272e2220 100644
--- a/docs/dynarmic/Design.md
+++ b/docs/dynarmic/Design.md
@@ -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/interface). Users specify how dynarmic's CPU core interacts with
+[`src/dynarmic/interface`](../../src/dynarmic/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/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)
+* 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)
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 (Eliminiation of redundant microinstructions, other speed improvements)
+3. Optimization (Elimination 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/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,
+ [`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,
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/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/).
+* 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/).
## 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/frontend/A32/decoder/arm.h):
+instruction table. Here is an example line from [`arm.h`](../../src/dynarmic/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/ir/ir_emitter.h). An example of a translation function follows:
+help of the [`IREmitter` class](../../src/dynarmic/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/ir/opcodes.inc).
+A complete list of microinstructions can be found in [src/dynarmic/ir/opcodes.inc](../../src/dynarmic/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}
-```c++
+```cpp
<u8> ReadMemory8(<u32> vaddr)
<u8> ReadMemory16(<u32> vaddr)
<u8> ReadMemory32(<u32> vaddr)
@@ -288,7 +288,7 @@ Memory access.
### Terminal: ReturnToDispatch
-```c++
+```cpp
SetTerm(IR::Term::ReturnToDispatch{})
```
@@ -297,7 +297,7 @@ The dispatcher will use the value in R15 to determine what comes next.
### Terminal: LinkBlock
-```c++
+```cpp
SetTerm(IR::Term::LinkBlock{next})
```
@@ -307,7 +307,7 @@ dispatcher, which will return control to the host.
### Terminal: LinkBlockFast
-```c++
+```cpp
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
-```c++
+```cpp
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
-```c++
+```cpp
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`
-```c++
+```cpp
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`
-```c++
+```cpp
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`
-```c++
+```cpp
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.
-```c++
+```cpp
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.
-```c++
+```cpp
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.
-```c++
+```cpp
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.
-`RSBSize` was chosen by performance testing. Note that this is bigger than the
+`RSB_SIZE` 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.
-```c++
+```cpp
struct JitState {
// ...
- static constexpr size_t RSBSize = 8; // MUST be a power of 2.
+ static constexpr size_t RSB_SIZE = 8; // MUST be a power of 2.
u32 rsb_ptr = 0;
- std::array<u64, RSBSize> rsb_location_descriptors;
- std::array<u64, RSBSize> rsb_codeptrs;
+ std::array<u64, RSB_SIZE> rsb_location_descriptors;
+ std::array<u64, RSB_SIZE> 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`.
-```c++
+```cpp
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::RSBSize - 1));
+ code->and_(index_reg, u32(JitState::RSB_SIZE - 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::RSBSize; ++i) {
+ for (size_t i = 0; i < JitState::RSB_SIZE; ++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:
-```c++
- for (i := 0 .. RSBSize-1)
+```cpp
+ for (i := 0 .. RSB_SIZE-1)
if (rsb_location_descriptors[i] == imm64)
goto label;
rsb_ptr++;
- rsb_ptr %= RSBSize;
+ rsb_ptr %= RSB_SIZE;
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.
-```c++
+```cpp
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::RSBSize; ++i) {
+ for (size_t i = 0; i < JitState::RSB_SIZE; ++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:
-```c++
+```cpp
rbx := ComputeUniqueHash()
rax := ReturnToDispatch
-for (i := 0 .. RSBSize-1)
+for (i := 0 .. RSB_SIZE-1)
if (rbx == rsb_location_descriptors[i])
rax = rsb_codeptrs[i]
goto rax
diff --git a/docs/dynarmic/README.md b/docs/dynarmic/README.md
index 376e1f6b37..0fa893d550 100644
--- a/docs/dynarmic/README.md
+++ b/docs/dynarmic/README.md
@@ -3,175 +3,20 @@ Dynarmic
A dynamic recompiler for ARM.
-Highlight features:
+*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.*
-- 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)
+Cortex-A57 (32 and 64 bit) is the emulated guest target. See [ArchVersion](../../src/dynarmic/src/dynarmic/interface/A32/arch_version.h).
-*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.*
+The only supported host architectures are x86-64, and AArch64. There are no plans to support any 32-bit architectures.
-### 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
-
-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
--------------
+See [an example usage](../../src/dynarmic/tests/print_info.cpp).
Design documentation can be found at [./Design.md](./Design.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
@@ -189,8 +34,8 @@ More general alternatives:
Disadvantages of Dynarmic
-------------------------
-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.
+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.
Known examples:
@@ -205,156 +50,6 @@ Use this code base at your own risk.
Legal
-----
-dynarmic is under a 0BSD license. See LICENSE.txt for more details.
-
-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.
-```
-
-### 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.
------------------------------------------------------------------------------
-ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満た
-す場合に限り、再頒布および使用が許可されます。
+Dynarmic is under a GPLv3 license, check the relevant file headers for more information.
-ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項
-を含めること。
-バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作
-権表示、本条件一覧、および下記免責条項を含めること。
-書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進
-に、著作権者の名前またはコントリビューターの名前を使用してはならない。
-本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供さ
-れており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性
-に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありません。
-著作権者もコントリビューターも、事由のいかんを問わず、 損害発生の原因いかんを
-問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法行為で
-あるかを問わず、仮にそのような損害が発生する可能性を知らされていたとしても、
-本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、使用の
-喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されない)直接
-損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害について、
-一切責任を負わないものとします。
-```
+Dynarmic uses several open-source libraries, whose licenses are included inside thereof.