mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-10 03:18:55 +02:00
Compare commits
19 commits
9e078aaffb
...
4c0916915f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c0916915f | ||
|
|
d646a57f75 | ||
|
|
e343ee9524 | ||
|
|
18ad42f996 | ||
|
|
cc553379d8 | ||
|
|
df113ea18b | ||
|
|
1d844296f4 | ||
|
|
fb53c236b2 | ||
|
|
6fa854001d | ||
|
|
ee124f3284 | ||
|
|
ac99ea96da | ||
|
|
d1b7824443 | ||
|
|
34fa39eae8 | ||
|
|
9ace6742d7 | ||
|
|
79f29abcba | ||
|
|
3ce5463d2d | ||
|
|
cae70c30fa | ||
|
|
bcceced96d | ||
|
|
82e374f66c |
34 changed files with 3123 additions and 1901 deletions
89
dist/icon_variations/aprilfools2026.svg
vendored
Normal file
89
dist/icon_variations/aprilfools2026.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 19 KiB |
1
dist/icon_variations/aprilfools2026_bgcolor
vendored
Normal file
1
dist/icon_variations/aprilfools2026_bgcolor
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#43fcfcff
|
||||||
|
|
@ -334,7 +334,7 @@ pacman -Syuu --needed --noconfirm $packages
|
||||||
<summary>HaikuOS</summary>
|
<summary>HaikuOS</summary>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel boost1.89_devel vulkan_devel qt6_base_devel qt6_declarative_devel libsdl2_devel ffmpeg7_devel libx11_devel enet_devel catch2_devel quazip1_qt5_devel qt6_5compat_devel glslang qt6_devel qt6_charts_devel
|
pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel boost1.90_devel vulkan_devel qt6_base_devel qt6_declarative_devel libsdl2_devel ffmpeg7_devel libx11_devel enet_devel catch2_devel quazip1_qt5_devel qt6_5compat_devel glslang qt6_devel qt6_charts_devel
|
||||||
```
|
```
|
||||||
|
|
||||||
[Caveats](./Caveats.md#haikuos).
|
[Caveats](./Caveats.md#haikuos).
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ Use this when you need to connect to a multiplayer room for LDN functionality in
|
||||||
- Multiplayer Options Configured in Eden Settings
|
- Multiplayer Options Configured in Eden Settings
|
||||||
- Network Access
|
- Network Access
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
There are 2 primary methods that you can use to connect to an existing room, depending on how the room is hosted.
|
There are 2 primary methods that you can use to connect to an existing room, depending on how the room is hosted.
|
||||||
|
|
||||||
- Joining a Public Lobby
|
- Joining a Public Lobby
|
||||||
|
|
@ -70,7 +70,7 @@ There are 2 primary methods that you can use to connect to an existing room, dep
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
### Joining a Public Lobby
|
## Joining a Public Lobby
|
||||||
1. Open Eden and navigate to *Multiplayer → Browse Public Game Lobby*.
|
1. Open Eden and navigate to *Multiplayer → Browse Public Game Lobby*.
|
||||||
2. The **Public Room Browser** will now open and display a list of publicly accessible rooms. Find one you want to connect to and double click it.
|
2. The **Public Room Browser** will now open and display a list of publicly accessible rooms. Find one you want to connect to and double click it.
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ If the hoster has not made the lobby public, or you don't want to find it in the
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Hosting a Multiplayer Room
|
## 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.
|
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.
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Hosting-a-Multiplayer-Room-2c357c2edaf6819481dbe8a99926cea2) for a version of this guide with images & visual elements.**
|
**Click [Here](https://evilperson1337.notion.site/Hosting-a-Multiplayer-Room-2c357c2edaf6819481dbe8a99926cea2) for a version of this guide with images & visual elements.**
|
||||||
|
|
@ -100,7 +100,7 @@ Use this guide for when you want to host a multiplayer lobby to play with others
|
||||||
- Network Access
|
- Network Access
|
||||||
- Ability to allow programs through the firewall on your device.
|
- Ability to allow programs through the firewall on your device.
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
1. Open Eden and navigate to *Emulation → Multiplayer → Create Room.*
|
1. Open Eden and navigate to *Emulation → Multiplayer → Create Room.*
|
||||||
2. Fill out the following information in the popup dialog box.
|
2. Fill out the following information in the popup dialog box.
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@ Use this guide for when you want to host a multiplayer lobby to play with others
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Access Your Multiplayer Room Externally
|
## 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.
|
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.
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for a version of this guide with images & visual elements.**
|
**Click [Here](https://evilperson1337.notion.site/Access-Your-Multiplayer-Room-Externally-2c357c2edaf681c0ab2ce2ee624d809d) for a version of this guide with images & visual elements.**
|
||||||
|
|
@ -129,9 +129,9 @@ Quite often the person with whom you want to play is located off of your interna
|
||||||
- Eden set up and Functioning
|
- Eden set up and Functioning
|
||||||
- Network Access
|
- Network Access
|
||||||
|
|
||||||
## Options
|
### Options
|
||||||
|
|
||||||
### Port Forwarding
|
#### Port Forwarding
|
||||||
|
|
||||||
- **Difficulty Level**: High
|
- **Difficulty Level**: High
|
||||||
|
|
||||||
|
|
@ -148,8 +148,9 @@ The process works by creating a static mapping—often called a “port-forward
|
||||||
|
|
||||||
For our purposes we would pick the port we want to expose (*e.g. 24872*) and we would access our router's configuration and create a port-forward rule to send the traffic from an external connection to your local machine over our specified port (*24872)*. The exact way to do so, varies greatly by router manufacturer - and sometimes require contacting your ISP to do so depending on your agreement. You can look up your router on [*portforward.com*](https://portforward.com/router.htm) which may have instructions on how to do so for your specific equipment. If it is not there, you will have to use Google/ChatGPT to determine the steps for your equipment.
|
For our purposes we would pick the port we want to expose (*e.g. 24872*) and we would access our router's configuration and create a port-forward rule to send the traffic from an external connection to your local machine over our specified port (*24872)*. The exact way to do so, varies greatly by router manufacturer - and sometimes require contacting your ISP to do so depending on your agreement. You can look up your router on [*portforward.com*](https://portforward.com/router.htm) which may have instructions on how to do so for your specific equipment. If it is not there, you will have to use Google/ChatGPT to determine the steps for your equipment.
|
||||||
|
|
||||||
|
Remember you can't have one port open for multiple devices at the same time - you must only host from one device (or do more convoluted networking which we will not cover here).
|
||||||
|
|
||||||
### Use a Tunnelling Service
|
#### Use a Tunnelling Service
|
||||||
- **Difficulty Level**: Easy
|
- **Difficulty Level**: Easy
|
||||||
|
|
||||||
<aside>
|
<aside>
|
||||||
|
|
@ -167,7 +168,7 @@ For our purposes we would spawn the listener for the port that way chose when ho
|
||||||
- [*Playit.GG*](https://playit.gg/)
|
- [*Playit.GG*](https://playit.gg/)
|
||||||
|
|
||||||
|
|
||||||
### Use a VPN Service
|
#### Use a VPN Service
|
||||||
|
|
||||||
- **Difficulty**: Easy
|
- **Difficulty**: Easy
|
||||||
|
|
||||||
|
|
@ -189,7 +190,7 @@ The VPN solution is a good compromise between the tunnelling solution and port f
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Finding the Server Information for a Multiplayer Room
|
## 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.
|
Use this guide when you need to determine the connection information for the Public Multiplayer Lobby you are connected to.
|
||||||
|
|
||||||
**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.**
|
**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.**
|
||||||
|
|
@ -198,7 +199,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
- Eden set up and configured
|
- Eden set up and configured
|
||||||
- Internet Access
|
- Internet Access
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
|
|
||||||
### Method 1: Grabbing the Address from the Log File
|
### Method 1: Grabbing the Address from the Log File
|
||||||
1. Open Eden and Connect to the room you want to identify.
|
1. Open Eden and Connect to the room you want to identify.
|
||||||
|
|
@ -222,7 +223,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
2. Open the terminal supported by your operating system.
|
2. Open the terminal supported by your operating system.
|
||||||
3. Run one of the following commands, replacing *<Name>* with the name of the server from step 1.
|
3. Run one of the following commands, replacing *<Name>* with the name of the server from step 1.
|
||||||
|
|
||||||
### PowerShell Command [Windows Users]
|
#### PowerShell Command [Windows Users]
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Calls the API to get the address and port information
|
# Calls the API to get the address and port information
|
||||||
|
|
@ -235,7 +236,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
#}
|
#}
|
||||||
```
|
```
|
||||||
|
|
||||||
### CURL Command [MacOS/Linux Users] **Requires jq*
|
#### CURL Command [MacOS/Linux Users] **Requires jq*
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Calls the API to get the address and port information
|
# Calls the API to get the address and port information
|
||||||
|
|
@ -252,7 +253,7 @@ Use this guide when you need to determine the connection information for the Pub
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Multiplayer for Local Co-Op Games
|
## 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.
|
Use this guide when you want to play with a friend on a different system for games that only support local co-op.
|
||||||
|
|
||||||
**Click [Here](https://evilperson1337.notion.site/Multiplayer-for-Local-Co-Op-Games-2c657c2edaf680c59975ec6b52022a2d) for a version of this guide with images & visual elements.**
|
**Click [Here](https://evilperson1337.notion.site/Multiplayer-for-Local-Co-Op-Games-2c657c2edaf680c59975ec6b52022a2d) for a version of this guide with images & visual elements.**
|
||||||
|
|
@ -271,7 +272,7 @@ In either situation at its core, we are emulating an input device on the host ma
|
||||||
- Parsec is free to use for personal, non-commercial use. For instructions on how to set up an account and install the client you should refer to the Parsec documentation on it's site.
|
- Parsec is free to use for personal, non-commercial use. For instructions on how to set up an account and install the client you should refer to the Parsec documentation on it's site.
|
||||||
- Parsec client installed on your machine and remote (friend's) machine
|
- Parsec client installed on your machine and remote (friend's) machine
|
||||||
|
|
||||||
## Steps
|
### Steps
|
||||||
|
|
||||||
<aside>
|
<aside>
|
||||||
|
|
||||||
|
|
@ -294,3 +295,22 @@ This guide will assume you are the one hosting the game and go over things *Pars
|
||||||
10. Set up the remote player's controller.
|
10. Set up the remote player's controller.
|
||||||
11. Hit **OK** to apply the changes.
|
11. Hit **OK** to apply the changes.
|
||||||
12. Launch the game you want to play and enter the co-op mode. How this works depends on the game, so you will have to look in the menus or online to find out.
|
12. Launch the game you want to play and enter the co-op mode. How this works depends on the game, so you will have to look in the menus or online to find out.
|
||||||
|
|
||||||
|
## Metaserver troubleshooting
|
||||||
|
|
||||||
|
If you can't connect to the metaserver, it's likely your ISP is blocking the requests.
|
||||||
|
|
||||||
|
### Linux and Steamdeck
|
||||||
|
|
||||||
|
Most Linux systems and Steamdeck should allow to modify the base `/etc/hosts` file, this should fix the DNS lookup issue; hence add the following to said file:
|
||||||
|
```
|
||||||
|
28.165.181.135 api.ynet-fun.xyz api.ynet-fun.xyz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Zapret
|
||||||
|
|
||||||
|
In `lists/list-general.txt` add the following:
|
||||||
|
```
|
||||||
|
api.ynet-fun.xyz
|
||||||
|
ynet-fun.xyz
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
#include <memory>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
|
|
||||||
namespace Common {
|
|
||||||
|
|
||||||
template <class Traits>
|
|
||||||
class LeastRecentlyUsedCache {
|
|
||||||
using ObjectType = typename Traits::ObjectType;
|
|
||||||
using TickType = typename Traits::TickType;
|
|
||||||
|
|
||||||
struct Item {
|
|
||||||
ObjectType obj;
|
|
||||||
TickType tick;
|
|
||||||
Item* next{};
|
|
||||||
Item* prev{};
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
LeastRecentlyUsedCache() : first_item{}, last_item{} {}
|
|
||||||
~LeastRecentlyUsedCache() = default;
|
|
||||||
|
|
||||||
size_t Insert(ObjectType obj, TickType tick) {
|
|
||||||
const auto new_id = Build();
|
|
||||||
auto& item = item_pool[new_id];
|
|
||||||
item.obj = obj;
|
|
||||||
item.tick = tick;
|
|
||||||
Attach(item);
|
|
||||||
return new_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Touch(size_t id, TickType tick) {
|
|
||||||
auto& item = item_pool[id];
|
|
||||||
if (item.tick >= tick) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
item.tick = tick;
|
|
||||||
if (&item == last_item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Detach(item);
|
|
||||||
Attach(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Free(size_t id) {
|
|
||||||
auto& item = item_pool[id];
|
|
||||||
Detach(item);
|
|
||||||
item.prev = nullptr;
|
|
||||||
item.next = nullptr;
|
|
||||||
free_items.push_back(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Func>
|
|
||||||
void ForEachItemBelow(TickType tick, Func&& func) {
|
|
||||||
static constexpr bool RETURNS_BOOL =
|
|
||||||
std::is_same_v<std::invoke_result<Func, ObjectType>, bool>;
|
|
||||||
Item* iterator = first_item;
|
|
||||||
while (iterator) {
|
|
||||||
if (static_cast<s64>(tick) - static_cast<s64>(iterator->tick) < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Item* next = iterator->next;
|
|
||||||
if constexpr (RETURNS_BOOL) {
|
|
||||||
if (func(iterator->obj)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
func(iterator->obj);
|
|
||||||
}
|
|
||||||
iterator = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t Build() {
|
|
||||||
if (free_items.empty()) {
|
|
||||||
const size_t item_id = item_pool.size();
|
|
||||||
auto& item = item_pool.emplace_back();
|
|
||||||
item.next = nullptr;
|
|
||||||
item.prev = nullptr;
|
|
||||||
return item_id;
|
|
||||||
}
|
|
||||||
const size_t item_id = free_items.front();
|
|
||||||
free_items.pop_front();
|
|
||||||
auto& item = item_pool[item_id];
|
|
||||||
item.next = nullptr;
|
|
||||||
item.prev = nullptr;
|
|
||||||
return item_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Attach(Item& item) {
|
|
||||||
if (!first_item) {
|
|
||||||
first_item = &item;
|
|
||||||
}
|
|
||||||
if (!last_item) {
|
|
||||||
last_item = &item;
|
|
||||||
} else {
|
|
||||||
item.prev = last_item;
|
|
||||||
last_item->next = &item;
|
|
||||||
item.next = nullptr;
|
|
||||||
last_item = &item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Detach(Item& item) {
|
|
||||||
if (item.prev) {
|
|
||||||
item.prev->next = item.next;
|
|
||||||
}
|
|
||||||
if (item.next) {
|
|
||||||
item.next->prev = item.prev;
|
|
||||||
}
|
|
||||||
if (&item == first_item) {
|
|
||||||
first_item = item.next;
|
|
||||||
if (first_item) {
|
|
||||||
first_item->prev = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (&item == last_item) {
|
|
||||||
last_item = item.prev;
|
|
||||||
if (last_item) {
|
|
||||||
last_item->next = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::deque<Item> item_pool;
|
|
||||||
std::deque<size_t> free_items;
|
|
||||||
Item* first_item{};
|
|
||||||
Item* last_item{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Common
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
|
@ -51,10 +51,12 @@ void RenderdocAPI::ToggleCapture() {
|
||||||
if (!rdoc_api) [[unlikely]] {
|
if (!rdoc_api) [[unlikely]] {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* api = static_cast<RENDERDOC_API_1_6_0*>(rdoc_api);
|
||||||
if (!is_capturing) {
|
if (!is_capturing) {
|
||||||
rdoc_api->StartFrameCapture(NULL, NULL);
|
api->StartFrameCapture(NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
rdoc_api->EndFrameCapture(NULL, NULL);
|
api->EndFrameCapture(NULL, NULL);
|
||||||
}
|
}
|
||||||
is_capturing = !is_capturing;
|
is_capturing = !is_capturing;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct RENDERDOC_API_1_7_0;
|
|
||||||
|
|
||||||
namespace Tools {
|
namespace Tools {
|
||||||
|
|
||||||
class RenderdocAPI {
|
class RenderdocAPI {
|
||||||
|
|
@ -18,7 +16,7 @@ public:
|
||||||
void ToggleCapture();
|
void ToggleCapture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RENDERDOC_API_1_7_0* rdoc_api{};
|
void* rdoc_api{};
|
||||||
bool is_capturing{false};
|
bool is_capturing{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -316,8 +316,8 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
|
||||||
return current_location->index;
|
return current_location->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(!ValueInfo(*current_location).realized);
|
ASSERT(!bool(ValueInfo(*current_location).realized));
|
||||||
ASSERT(ValueInfo(*current_location).locked);
|
ASSERT(bool(ValueInfo(*current_location).locked));
|
||||||
|
|
||||||
if constexpr (required_kind == HostLoc::Kind::Gpr) {
|
if constexpr (required_kind == HostLoc::Kind::Gpr) {
|
||||||
const int new_location_index = AllocateRegister(gprs, gpr_order);
|
const int new_location_index = AllocateRegister(gprs, gpr_order);
|
||||||
|
|
|
||||||
|
|
@ -1985,6 +1985,13 @@ void EmitX64::EmitFPVectorToHalf32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
// output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
|
// output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
template<size_t fsize, bool unsigned_, FP::RoundingMode rounding_mode, size_t fbits>
|
||||||
|
static void EmitFPVectorToFixedThunk(VectorArray<mcl::unsigned_integer_of_size<fsize>>& output, const VectorArray<mcl::unsigned_integer_of_size<fsize>>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
||||||
|
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||||
|
for (size_t i = 0; i < output.size(); ++i)
|
||||||
|
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
|
||||||
|
}
|
||||||
|
|
||||||
template<size_t fsize, bool unsigned_>
|
template<size_t fsize, bool unsigned_>
|
||||||
void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
const size_t fbits = inst->GetArg(1).GetU8();
|
const size_t fbits = inst->GetArg(1).GetU8();
|
||||||
|
|
@ -2106,43 +2113,88 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
ctx.reg_alloc.DefineValue(code, inst, src);
|
ctx.reg_alloc.DefineValue(code, inst, src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto const fpt_fn = [fbits, rounding]() -> void (*)(VectorArray<mcl::unsigned_integer_of_size<fsize>>& output, const VectorArray<mcl::unsigned_integer_of_size<fsize>>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
||||||
|
#define ROUNDING_MODE_CASE(CASE, N) \
|
||||||
|
if (rounding == FP::RoundingMode::CASE && fsize >= (N) && fbits == (N)) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, N>;
|
||||||
|
#define ROUNDING_MODE_SWITCH(CASE) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x00) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x01) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x02) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x03) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x04) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x05) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x06) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x07) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x08) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x09) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x0a) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x0b) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x0c) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x0d) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x0e) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x0f) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x10) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x11) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x12) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x13) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x14) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x15) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x16) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x17) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x18) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x19) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x1a) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x1b) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x1c) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x1d) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x1e) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x1f) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x20) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x21) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x22) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x23) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x24) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x25) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x26) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x27) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x28) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x29) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x2a) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x2b) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x2c) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x2d) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x2e) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x2f) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x30) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x31) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x32) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x33) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x34) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x35) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x36) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x37) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x38) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x39) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x3a) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x3b) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x3c) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x3d) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x3e) \
|
||||||
|
ROUNDING_MODE_CASE(CASE, 0x3f)
|
||||||
|
|
||||||
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC
|
// FUCK YOU MSVC, FUCKING DEPTH CANT EVEN HANDLE 8+16+32+64 DEPTH OF A ELSE STATMENT YOU FUCKING STUPID
|
||||||
auto const func = [rounding]() -> void(*)(VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
// BURN MSVC BURN IT STUPID COMPILER CAN'T EVEN COMPILE THE MOST BASIC C++
|
||||||
switch (rounding) {
|
ROUNDING_MODE_SWITCH(ToNearest_TieEven)
|
||||||
case FP::RoundingMode::ToNearest_TieEven:
|
ROUNDING_MODE_SWITCH(TowardsPlusInfinity)
|
||||||
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
ROUNDING_MODE_SWITCH(TowardsMinusInfinity)
|
||||||
for (size_t i = 0; i < output.size(); ++i)
|
ROUNDING_MODE_SWITCH(TowardsZero)
|
||||||
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToNearest_TieEven, fpsr));
|
ROUNDING_MODE_SWITCH(ToNearest_TieAwayFromZero)
|
||||||
};
|
#undef ROUNDING_MODE_SWITCH
|
||||||
case FP::RoundingMode::TowardsPlusInfinity:
|
#undef ROUNDING_MODE_CASE
|
||||||
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
return nullptr;
|
||||||
for (size_t i = 0; i < output.size(); ++i)
|
|
||||||
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsPlusInfinity, fpsr));
|
|
||||||
};
|
|
||||||
case FP::RoundingMode::TowardsMinusInfinity:
|
|
||||||
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
|
||||||
for (size_t i = 0; i < output.size(); ++i)
|
|
||||||
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsMinusInfinity, fpsr));
|
|
||||||
};
|
|
||||||
case FP::RoundingMode::TowardsZero:
|
|
||||||
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
|
||||||
for (size_t i = 0; i < output.size(); ++i)
|
|
||||||
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsZero, fpsr));
|
|
||||||
};
|
|
||||||
case FP::RoundingMode::ToNearest_TieAwayFromZero:
|
|
||||||
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
|
||||||
for (size_t i = 0; i < output.size(); ++i)
|
|
||||||
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToNearest_TieAwayFromZero, fpsr));
|
|
||||||
};
|
|
||||||
case FP::RoundingMode::ToOdd:
|
|
||||||
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
|
||||||
for (size_t i = 0; i < output.size(); ++i)
|
|
||||||
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToOdd, fpsr));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}();
|
}();
|
||||||
EmitTwoOpFallback<3>(code, ctx, inst, func);
|
|
||||||
|
EmitTwoOpFallback<3>(code, ctx, inst, fpt_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitFPVectorToSignedFixed16(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitFPVectorToSignedFixed16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
}
|
}
|
||||||
inline void ReadLock() noexcept {
|
inline void ReadLock() noexcept {
|
||||||
ASSERT(size_t(is_being_used_count) + 1 < (std::numeric_limits<decltype(is_being_used_count)>::max)());
|
ASSERT(size_t(is_being_used_count) + 1 < (std::numeric_limits<decltype(is_being_used_count)>::max)());
|
||||||
ASSERT(!is_scratch);
|
ASSERT(!bool(is_scratch));
|
||||||
is_being_used_count++;
|
is_being_used_count++;
|
||||||
}
|
}
|
||||||
inline void WriteLock() noexcept {
|
inline void WriteLock() noexcept {
|
||||||
|
|
|
||||||
|
|
@ -36,25 +36,19 @@ inline size_t ToFastLookupIndexArm(u32 instruction) noexcept {
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
constexpr ArmDecodeTable<V> GetArmDecodeTable() noexcept {
|
static ArmDecodeTable<V> GetArmDecodeTable() noexcept {
|
||||||
std::vector<ArmMatcher<V>> list = {
|
ArmDecodeTable<V> table{};
|
||||||
|
for (size_t i = 0; i < table.size(); ++i) {
|
||||||
|
// PLEASE HEAP ELLIDE
|
||||||
|
for (auto const& e : std::vector<ArmMatcher<V>>{
|
||||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(ArmMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(ArmMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||||
#include "./arm.inc"
|
#include "./arm.inc"
|
||||||
#undef INST
|
#undef INST
|
||||||
};
|
}) {
|
||||||
|
auto const expect = detail::ToFastLookupIndexArm(e.GetExpected());
|
||||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
auto const mask = detail::ToFastLookupIndexArm(e.GetMask());
|
||||||
std::stable_sort(list.begin(), list.end(), [](const auto& matcher1, const auto& matcher2) {
|
|
||||||
return mcl::bit::count_ones(matcher1.GetMask()) > mcl::bit::count_ones(matcher2.GetMask());
|
|
||||||
});
|
|
||||||
|
|
||||||
ArmDecodeTable<V> table{};
|
|
||||||
for (size_t i = 0; i < table.size(); ++i) {
|
|
||||||
for (auto matcher : list) {
|
|
||||||
const auto expect = detail::ToFastLookupIndexArm(matcher.GetExpected());
|
|
||||||
const auto mask = detail::ToFastLookupIndexArm(matcher.GetMask());
|
|
||||||
if ((i & mask) == expect) {
|
if ((i & mask) == expect) {
|
||||||
table[i].push_back(matcher);
|
table[i].push_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +56,7 @@ constexpr ArmDecodeTable<V> GetArmDecodeTable() noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruction) noexcept {
|
static std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruction) noexcept {
|
||||||
alignas(64) static const auto table = GetArmDecodeTable<V>();
|
alignas(64) static const auto table = GetArmDecodeTable<V>();
|
||||||
const auto matches_instruction = [instruction](const auto& matcher) {
|
const auto matches_instruction = [instruction](const auto& matcher) {
|
||||||
return matcher.Matches(instruction);
|
return matcher.Matches(instruction);
|
||||||
|
|
@ -73,7 +67,7 @@ std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruc
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::string_view> GetNameARM(u32 inst) noexcept {
|
static std::optional<std::string_view> GetNameARM(u32 inst) noexcept {
|
||||||
std::vector<std::pair<std::string_view, ArmMatcher<V>>> list = {
|
std::vector<std::pair<std::string_view, ArmMatcher<V>>> list = {
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(ArmMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(ArmMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
||||||
#include "./arm.inc"
|
#include "./arm.inc"
|
||||||
|
|
|
||||||
|
|
@ -1,316 +1,265 @@
|
||||||
// Barrier instructions
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
INST(arm_DMB, "DMB", "1111010101111111111100000101oooo") // v7
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
INST(arm_DSB, "DSB", "1111010101111111111100000100oooo") // v7
|
// DO NOT REORDER
|
||||||
INST(arm_ISB, "ISB", "1111010101111111111100000110oooo") // v7
|
|
||||||
|
|
||||||
// Branch instructions
|
INST(arm_CLREX, "CLREX", "11110101011111111111000000011111")
|
||||||
INST(arm_BLX_imm, "BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv") // v5
|
INST(arm_SETEND, "SETEND", "1111000100000001000000e000000000")
|
||||||
INST(arm_BLX_reg, "BLX (reg)", "cccc000100101111111111110011mmmm") // v5
|
INST(arm_DMB, "DMB", "1111010101111111111100000101oooo")
|
||||||
INST(arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv") // v1
|
INST(arm_DSB, "DSB", "1111010101111111111100000100oooo")
|
||||||
INST(arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv") // v1
|
INST(arm_ISB, "ISB", "1111010101111111111100000110oooo")
|
||||||
INST(arm_BX, "BX", "cccc000100101111111111110001mmmm") // v4T
|
INST(arm_SEV, "SEV", "----0011001000001111000000000100")
|
||||||
INST(arm_BXJ, "BXJ", "cccc000100101111111111110010mmmm") // v5J
|
INST(arm_SEVL, "SEVL", "----0011001000001111000000000101")
|
||||||
|
INST(arm_WFE, "WFE", "----0011001000001111000000000010")
|
||||||
// CRC32 instructions
|
INST(arm_WFI, "WFI", "----0011001000001111000000000011")
|
||||||
INST(arm_CRC32, "CRC32", "cccc00010zz0nnnndddd00000100mmmm") // v8
|
INST(arm_YIELD, "YIELD", "----0011001000001111000000000001")
|
||||||
INST(arm_CRC32C, "CRC32C", "cccc00010zz0nnnndddd00100100mmmm") // v8
|
INST(arm_NOP, "NOP", "----0011001000001111000000000000")
|
||||||
|
INST(arm_RFE, "RFE", "1111100--0-1----0000101000000000")
|
||||||
// Coprocessor instructions
|
INST(arm_BLX_reg, "BLX (reg)", "cccc000100101111111111110011mmmm")
|
||||||
INST(arm_CDP, "CDP", "cccc1110ooooNNNNDDDDppppooo0MMMM") // v2 (CDP2: v5)
|
INST(arm_BX, "BX", "cccc000100101111111111110001mmmm")
|
||||||
INST(arm_LDC, "LDC", "cccc110pudw1nnnnDDDDppppvvvvvvvv") // v2 (LDC2: v5)
|
INST(arm_BXJ, "BXJ", "cccc000100101111111111110010mmmm")
|
||||||
INST(arm_MCR, "MCR", "cccc1110ooo0NNNNttttppppooo1MMMM") // v2 (MCR2: v5)
|
INST(arm_NOP, "Reserved Hint", "----001100100000111100000000----")
|
||||||
INST(arm_MCRR, "MCRR", "cccc11000100uuuuttttppppooooMMMM") // v5E (MCRR2: v6)
|
INST(arm_MRS, "MRS", "cccc000100001111dddd000000000000")
|
||||||
INST(arm_MRC, "MRC", "cccc1110ooo1NNNNttttppppooo1MMMM") // v2 (MRC2: v5)
|
INST(arm_SRS, "SRS", "1111100--1-0110100000101000-----")
|
||||||
INST(arm_MRRC, "MRRC", "cccc11000101uuuuttttppppooooMMMM") // v5E (MRRC2: v6)
|
INST(arm_CPS, "CPS", "111100010000---00000000---0-----")
|
||||||
INST(arm_STC, "STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv") // v2 (STC2: v5)
|
INST(arm_STL, "STL", "cccc00011000nnnn111111001001tttt")
|
||||||
|
INST(arm_LDA, "LDA", "cccc00011001nnnndddd110010011111")
|
||||||
// Data Processing instructions
|
INST(arm_LDAEX, "LDAEX", "cccc00011001nnnndddd111010011111")
|
||||||
INST(arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_LDREX, "LDREX", "cccc00011001nnnndddd111110011111")
|
||||||
INST(arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_LDAEXD, "LDAEXD", "cccc00011011nnnndddd111010011111")
|
||||||
INST(arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_LDREXD, "LDREXD", "cccc00011011nnnndddd111110011111")
|
||||||
INST(arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_STLB, "STLB", "cccc00011100nnnn111111001001tttt")
|
||||||
INST(arm_ADD_reg, "ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_LDAB, "LDAB", "cccc00011101nnnndddd110010011111")
|
||||||
INST(arm_ADD_rsr, "ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_LDAEXB, "LDAEXB", "cccc00011101nnnndddd111010011111")
|
||||||
INST(arm_AND_imm, "AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_LDREXB, "LDREXB", "cccc00011101nnnndddd111110011111")
|
||||||
INST(arm_AND_reg, "AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_STLH, "STLH", "cccc00011110nnnn111111001001mmmm")
|
||||||
INST(arm_AND_rsr, "AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_LDAH, "LDAH", "cccc00011111nnnndddd110010011111")
|
||||||
INST(arm_BIC_imm, "BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_LDAEXH, "LDAEXH", "cccc00011111nnnndddd111010011111")
|
||||||
INST(arm_BIC_reg, "BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111")
|
||||||
INST(arm_BIC_rsr, "BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_CLZ, "CLZ", "cccc000101101111dddd11110001mmmm")
|
||||||
INST(arm_CMN_imm, "CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv") // v1
|
INST(arm_RBIT, "RBIT", "cccc011011111111dddd11110011mmmm")
|
||||||
INST(arm_CMN_reg, "CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm") // v1
|
INST(arm_REV, "REV", "cccc011010111111dddd11110011mmmm")
|
||||||
INST(arm_CMN_rsr, "CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm") // v1
|
INST(arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm")
|
||||||
INST(arm_CMP_imm, "CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv") // v1
|
INST(arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm")
|
||||||
INST(arm_CMP_reg, "CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm") // v1
|
INST(arm_MSR_reg, "MSR (reg)", "cccc00010010mmmm111100000000nnnn")
|
||||||
INST(arm_CMP_rsr, "CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm") // v1
|
INST(arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm")
|
||||||
INST(arm_EOR_imm, "EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_SXTB16, "SXTB16", "cccc011010001111ddddrr000111mmmm")
|
||||||
INST(arm_EOR_reg, "EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_SXTH, "SXTH", "cccc011010111111ddddrr000111mmmm")
|
||||||
INST(arm_EOR_rsr, "EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_UXTB, "UXTB", "cccc011011101111ddddrr000111mmmm")
|
||||||
INST(arm_MOV_imm, "MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv") // v1
|
INST(arm_UXTB16, "UXTB16", "cccc011011001111ddddrr000111mmmm")
|
||||||
INST(arm_MOV_reg, "MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm") // v1
|
INST(arm_UXTH, "UXTH", "cccc011011111111ddddrr000111mmmm")
|
||||||
INST(arm_MOV_rsr, "MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm") // v1
|
INST(arm_UDF, "UDF", "111001111111------------1111----")
|
||||||
INST(arm_MVN_imm, "MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv") // v1
|
INST(arm_NOP, "Reserved Hint", "----0011001000001111------------")
|
||||||
INST(arm_MVN_reg, "MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm") // v1
|
INST(arm_SWP, "SWP", "cccc00010000nnnntttt00001001uuuu")
|
||||||
INST(arm_MVN_rsr, "MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm") // v1
|
INST(arm_SWPB, "SWPB", "cccc00010100nnnntttt00001001uuuu")
|
||||||
INST(arm_ORR_imm, "ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_STLEX, "STLEX", "cccc00011000nnnndddd11101001tttt")
|
||||||
INST(arm_ORR_reg, "ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_STREX, "STREX", "cccc00011000nnnndddd11111001mmmm")
|
||||||
INST(arm_ORR_rsr, "ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_STLEXD, "STLEXD", "cccc00011010nnnndddd11101001mmmm")
|
||||||
INST(arm_RSB_imm, "RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_STREXD, "STREXD", "cccc00011010nnnndddd11111001mmmm")
|
||||||
INST(arm_RSB_reg, "RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_STLEXB, "STLEXB", "cccc00011100nnnndddd11101001mmmm")
|
||||||
INST(arm_RSB_rsr, "RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_STREXB, "STREXB", "cccc00011100nnnndddd11111001mmmm")
|
||||||
INST(arm_RSC_imm, "RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_STLEXH, "STLEXH", "cccc00011110nnnndddd11101001mmmm")
|
||||||
INST(arm_RSC_reg, "RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_STREXH, "STREXH", "cccc00011110nnnndddd11111001mmmm")
|
||||||
INST(arm_RSC_rsr, "RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_SEL, "SEL", "cccc01101000nnnndddd11111011mmmm")
|
||||||
INST(arm_SBC_imm, "SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_USAD8, "USAD8", "cccc01111000dddd1111mmmm0001nnnn")
|
||||||
INST(arm_SBC_reg, "SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_SSAT16, "SSAT16", "cccc01101010vvvvdddd11110011nnnn")
|
||||||
INST(arm_SBC_rsr, "SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_USAT16, "USAT16", "cccc01101110vvvvdddd11110011nnnn")
|
||||||
INST(arm_SUB_imm, "SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv") // v1
|
INST(arm_SDIV, "SDIV", "cccc01110001dddd1111mmmm0001nnnn")
|
||||||
INST(arm_SUB_reg, "SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm") // v1
|
INST(arm_UDIV, "UDIV", "cccc01110011dddd1111mmmm0001nnnn")
|
||||||
INST(arm_SUB_rsr, "SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm") // v1
|
INST(arm_SADD8, "SADD8", "cccc01100001nnnndddd11111001mmmm")
|
||||||
INST(arm_TEQ_imm, "TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv") // v1
|
INST(arm_SADD16, "SADD16", "cccc01100001nnnndddd11110001mmmm")
|
||||||
INST(arm_TEQ_reg, "TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm") // v1
|
INST(arm_SASX, "SASX", "cccc01100001nnnndddd11110011mmmm")
|
||||||
INST(arm_TEQ_rsr, "TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm") // v1
|
INST(arm_SSAX, "SSAX", "cccc01100001nnnndddd11110101mmmm")
|
||||||
INST(arm_TST_imm, "TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv") // v1
|
INST(arm_SSUB8, "SSUB8", "cccc01100001nnnndddd11111111mmmm")
|
||||||
INST(arm_TST_reg, "TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm") // v1
|
INST(arm_SSUB16, "SSUB16", "cccc01100001nnnndddd11110111mmmm")
|
||||||
INST(arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm") // v1
|
INST(arm_UADD8, "UADD8", "cccc01100101nnnndddd11111001mmmm")
|
||||||
|
INST(arm_UADD16, "UADD16", "cccc01100101nnnndddd11110001mmmm")
|
||||||
// Exception Generating instructions
|
INST(arm_UASX, "UASX", "cccc01100101nnnndddd11110011mmmm")
|
||||||
INST(arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv") // v5
|
INST(arm_USAX, "USAX", "cccc01100101nnnndddd11110101mmmm")
|
||||||
INST(arm_SVC, "SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv") // v1
|
INST(arm_USUB8, "USUB8", "cccc01100101nnnndddd11111111mmmm")
|
||||||
INST(arm_UDF, "UDF", "111001111111------------1111----")
|
INST(arm_USUB16, "USUB16", "cccc01100101nnnndddd11110111mmmm")
|
||||||
|
INST(arm_QADD8, "QADD8", "cccc01100010nnnndddd11111001mmmm")
|
||||||
// Extension instructions
|
INST(arm_QADD16, "QADD16", "cccc01100010nnnndddd11110001mmmm")
|
||||||
INST(arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm") // v6
|
INST(arm_QASX, "QASX", "cccc01100010nnnndddd11110011mmmm")
|
||||||
INST(arm_SXTB16, "SXTB16", "cccc011010001111ddddrr000111mmmm") // v6
|
INST(arm_QSAX, "QSAX", "cccc01100010nnnndddd11110101mmmm")
|
||||||
INST(arm_SXTH, "SXTH", "cccc011010111111ddddrr000111mmmm") // v6
|
INST(arm_QSUB8, "QSUB8", "cccc01100010nnnndddd11111111mmmm")
|
||||||
INST(arm_SXTAB, "SXTAB", "cccc01101010nnnnddddrr000111mmmm") // v6
|
INST(arm_QSUB16, "QSUB16", "cccc01100010nnnndddd11110111mmmm")
|
||||||
INST(arm_SXTAB16, "SXTAB16", "cccc01101000nnnnddddrr000111mmmm") // v6
|
INST(arm_UQADD8, "UQADD8", "cccc01100110nnnndddd11111001mmmm")
|
||||||
INST(arm_SXTAH, "SXTAH", "cccc01101011nnnnddddrr000111mmmm") // v6
|
INST(arm_UQADD16, "UQADD16", "cccc01100110nnnndddd11110001mmmm")
|
||||||
INST(arm_UXTB, "UXTB", "cccc011011101111ddddrr000111mmmm") // v6
|
INST(arm_UQASX, "UQASX", "cccc01100110nnnndddd11110011mmmm")
|
||||||
INST(arm_UXTB16, "UXTB16", "cccc011011001111ddddrr000111mmmm") // v6
|
INST(arm_UQSAX, "UQSAX", "cccc01100110nnnndddd11110101mmmm")
|
||||||
INST(arm_UXTH, "UXTH", "cccc011011111111ddddrr000111mmmm") // v6
|
INST(arm_UQSUB8, "UQSUB8", "cccc01100110nnnndddd11111111mmmm")
|
||||||
INST(arm_UXTAB, "UXTAB", "cccc01101110nnnnddddrr000111mmmm") // v6
|
INST(arm_UQSUB16, "UQSUB16", "cccc01100110nnnndddd11110111mmmm")
|
||||||
INST(arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm") // v6
|
INST(arm_SHADD8, "SHADD8", "cccc01100011nnnndddd11111001mmmm")
|
||||||
INST(arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm") // v6
|
INST(arm_SHADD16, "SHADD16", "cccc01100011nnnndddd11110001mmmm")
|
||||||
|
INST(arm_SHASX, "SHASX", "cccc01100011nnnndddd11110011mmmm")
|
||||||
// Hint instructions
|
INST(arm_SHSAX, "SHSAX", "cccc01100011nnnndddd11110101mmmm")
|
||||||
INST(arm_PLD_imm, "PLD (imm)", "11110101uz01nnnn1111iiiiiiiiiiii") // v5E for PLD; v7 for PLDW
|
INST(arm_SHSUB8, "SHSUB8", "cccc01100011nnnndddd11111111mmmm")
|
||||||
INST(arm_PLD_reg, "PLD (reg)", "11110111uz01nnnn1111iiiiitt0mmmm") // v5E for PLD; v7 for PLDW
|
INST(arm_SHSUB16, "SHSUB16", "cccc01100011nnnndddd11110111mmmm")
|
||||||
INST(arm_SEV, "SEV", "----0011001000001111000000000100") // v6K
|
INST(arm_UHADD8, "UHADD8", "cccc01100111nnnndddd11111001mmmm")
|
||||||
INST(arm_SEVL, "SEVL", "----0011001000001111000000000101") // v8
|
INST(arm_UHADD16, "UHADD16", "cccc01100111nnnndddd11110001mmmm")
|
||||||
INST(arm_WFE, "WFE", "----0011001000001111000000000010") // v6K
|
INST(arm_UHASX, "UHASX", "cccc01100111nnnndddd11110011mmmm")
|
||||||
INST(arm_WFI, "WFI", "----0011001000001111000000000011") // v6K
|
INST(arm_UHSAX, "UHSAX", "cccc01100111nnnndddd11110101mmmm")
|
||||||
INST(arm_YIELD, "YIELD", "----0011001000001111000000000001") // v6K
|
INST(arm_UHSUB8, "UHSUB8", "cccc01100111nnnndddd11111111mmmm")
|
||||||
INST(arm_NOP, "Reserved Hint", "----0011001000001111------------")
|
INST(arm_UHSUB16, "UHSUB16", "cccc01100111nnnndddd11110111mmmm")
|
||||||
INST(arm_NOP, "Reserved Hint", "----001100100000111100000000----")
|
INST(arm_QADD, "QADD", "cccc00010000nnnndddd00000101mmmm")
|
||||||
|
INST(arm_QSUB, "QSUB", "cccc00010010nnnndddd00000101mmmm")
|
||||||
// Synchronization Primitive instructions
|
INST(arm_QDADD, "QDADD", "cccc00010100nnnndddd00000101mmmm")
|
||||||
INST(arm_CLREX, "CLREX", "11110101011111111111000000011111") // v6K
|
INST(arm_QDSUB, "QDSUB", "cccc00010110nnnndddd00000101mmmm")
|
||||||
INST(arm_SWP, "SWP", "cccc00010000nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
INST(arm_PLD_reg, "PLD (reg)", "11110111uz01nnnn1111iiiiitt0mmmm")
|
||||||
INST(arm_SWPB, "SWPB", "cccc00010100nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
INST(arm_LDRHT, "LDRHT (A1)", "----0000-1111111--------1011----")
|
||||||
INST(arm_STL, "STL", "cccc00011000nnnn111111001001tttt") // v8
|
INST(arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----")
|
||||||
INST(arm_STLEX, "STLEX", "cccc00011000nnnndddd11101001tttt") // v8
|
INST(arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----")
|
||||||
INST(arm_STREX, "STREX", "cccc00011000nnnndddd11111001mmmm") // v6
|
INST(arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----")
|
||||||
INST(arm_LDA, "LDA", "cccc00011001nnnndddd110010011111") // v8
|
INST(arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----")
|
||||||
INST(arm_LDAEX, "LDAEX", "cccc00011001nnnndddd111010011111") // v8
|
INST(arm_LDRD_lit, "LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv")
|
||||||
INST(arm_LDREX, "LDREX", "cccc00011001nnnndddd111110011111") // v6
|
INST(arm_LDRSB_lit, "LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv")
|
||||||
INST(arm_STLEXD, "STLEXD", "cccc00011010nnnndddd11101001mmmm") // v8
|
INST(arm_LDRSH_lit, "LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv")
|
||||||
INST(arm_STREXD, "STREXD", "cccc00011010nnnndddd11111001mmmm") // v6K
|
INST(arm_MUL, "MUL", "cccc0000000Sdddd0000mmmm1001nnnn")
|
||||||
INST(arm_LDAEXD, "LDAEXD", "cccc00011011nnnndddd111010011111") // v8
|
INST(arm_SMULWy, "SMULWY", "cccc00010010dddd0000mmmm1y10nnnn")
|
||||||
INST(arm_LDREXD, "LDREXD", "cccc00011011nnnndddd111110011111") // v6K
|
INST(arm_SMMUL, "SMMUL", "cccc01110101dddd1111mmmm00R1nnnn")
|
||||||
INST(arm_STLB, "STLB", "cccc00011100nnnn111111001001tttt") // v8
|
INST(arm_SMUAD, "SMUAD", "cccc01110000dddd1111mmmm00M1nnnn")
|
||||||
INST(arm_STLEXB, "STLEXB", "cccc00011100nnnndddd11101001mmmm") // v8
|
INST(arm_SMUSD, "SMUSD", "cccc01110000dddd1111mmmm01M1nnnn")
|
||||||
INST(arm_STREXB, "STREXB", "cccc00011100nnnndddd11111001mmmm") // v6K
|
INST(arm_CRC32, "CRC32", "cccc00010zz0nnnndddd00000100mmmm")
|
||||||
INST(arm_LDAB, "LDAB", "cccc00011101nnnndddd110010011111") // v8
|
INST(arm_CRC32C, "CRC32C", "cccc00010zz0nnnndddd00100100mmmm")
|
||||||
INST(arm_LDAEXB, "LDAEXB", "cccc00011101nnnndddd111010011111") // v8
|
INST(arm_CMN_rsr, "CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm")
|
||||||
INST(arm_LDREXB, "LDREXB", "cccc00011101nnnndddd111110011111") // v6K
|
INST(arm_CMP_rsr, "CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm")
|
||||||
INST(arm_STLH, "STLH", "cccc00011110nnnn111111001001mmmm") // v8
|
INST(arm_TEQ_rsr, "TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm")
|
||||||
INST(arm_STLEXH, "STLEXH", "cccc00011110nnnndddd11101001mmmm") // v8
|
INST(arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm")
|
||||||
INST(arm_STREXH, "STREXH", "cccc00011110nnnndddd11111001mmmm") // v6K
|
INST(arm_SXTAB, "SXTAB", "cccc01101010nnnnddddrr000111mmmm")
|
||||||
INST(arm_LDAH, "LDAH", "cccc00011111nnnndddd110010011111") // v8
|
INST(arm_SXTAB16, "SXTAB16", "cccc01101000nnnnddddrr000111mmmm")
|
||||||
INST(arm_LDAEXH, "LDAEXH", "cccc00011111nnnndddd111010011111") // v8
|
INST(arm_SXTAH, "SXTAH", "cccc01101011nnnnddddrr000111mmmm")
|
||||||
INST(arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111") // v6K
|
INST(arm_UXTAB, "UXTAB", "cccc01101110nnnnddddrr000111mmmm")
|
||||||
|
INST(arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm")
|
||||||
// Load/Store instructions
|
INST(arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm")
|
||||||
INST(arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------") // v1
|
INST(arm_PLD_imm, "PLD (imm)", "11110101uz01nnnn1111iiiiiiiiiiii")
|
||||||
INST(arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----") // v1
|
INST(arm_BFC, "BFC", "cccc0111110vvvvvddddvvvvv0011111")
|
||||||
INST(arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----") // v6T2
|
INST(arm_SMULxy, "SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn")
|
||||||
INST(arm_LDRHT, "LDRHT (A1)", "----0000-1111111--------1011----") // v6T2
|
INST(arm_CMN_reg, "CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm")
|
||||||
INST(arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----") // v6T2
|
INST(arm_CMP_reg, "CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm")
|
||||||
INST(arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----") // v6T2
|
INST(arm_MOV_rsr, "MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm")
|
||||||
INST(arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----") // v6T2
|
INST(arm_MVN_rsr, "MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm")
|
||||||
INST(arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----") // v6T2
|
INST(arm_TEQ_reg, "TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm")
|
||||||
INST(arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----") // v6T2
|
INST(arm_TST_reg, "TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm")
|
||||||
INST(arm_LDRT, "LDRT (A1)", "----0100-011--------------------") // v1
|
INST(arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm")
|
||||||
INST(arm_LDRT, "LDRT (A2)", "----0110-011---------------0----") // v1
|
INST(arm_LDRH_lit, "LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv")
|
||||||
INST(arm_STRBT, "STRBT (A1)", "----0100-110--------------------") // v1
|
INST(arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm")
|
||||||
INST(arm_STRBT, "STRBT (A2)", "----0110-110---------------0----") // v1
|
INST(arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm")
|
||||||
INST(arm_STRHT, "STRHT (A1)", "----0000-110------------1011----") // v6T2
|
INST(arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm")
|
||||||
INST(arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----") // v6T2
|
INST(arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm")
|
||||||
INST(arm_STRT, "STRT (A1)", "----0100-010--------------------") // v1
|
INST(arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm")
|
||||||
INST(arm_STRT, "STRT (A2)", "----0110-010---------------0----") // v1
|
INST(arm_CMN_imm, "CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv")
|
||||||
INST(arm_LDR_lit, "LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv") // v1
|
INST(arm_CMP_imm, "CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv")
|
||||||
INST(arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv") // v1
|
INST(arm_MOV_reg, "MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm")
|
||||||
INST(arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm") // v1
|
INST(arm_MVN_reg, "MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm")
|
||||||
INST(arm_LDRB_lit, "LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv") // v1
|
INST(arm_TEQ_imm, "TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv")
|
||||||
INST(arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv") // v1
|
INST(arm_TST_imm, "TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv")
|
||||||
INST(arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm") // v1
|
INST(arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv")
|
||||||
INST(arm_LDRD_lit, "LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv") // v5E
|
INST(arm_USADA8, "USADA8", "cccc01111000ddddaaaammmm0001nnnn")
|
||||||
INST(arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv") // v5E
|
INST(arm_MLS, "MLS", "cccc00000110ddddaaaammmm1001nnnn")
|
||||||
INST(arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm") // v5E
|
INST(arm_UMAAL, "UMAAL", "cccc00000100ddddaaaammmm1001nnnn")
|
||||||
INST(arm_LDRH_lit, "LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv") // v4
|
INST(arm_MSR_imm, "MSR (imm)", "cccc00110010mmmm1111rrrrvvvvvvvv")
|
||||||
INST(arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv") // v4
|
INST(arm_MOV_imm, "MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv")
|
||||||
INST(arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm") // v4
|
INST(arm_MVN_imm, "MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv")
|
||||||
INST(arm_LDRSB_lit, "LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv") // v4
|
INST(arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----")
|
||||||
INST(arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv") // v4
|
INST(arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----")
|
||||||
INST(arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm") // v4
|
INST(arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----")
|
||||||
INST(arm_LDRSH_lit, "LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv") // v4
|
INST(arm_STRHT, "STRHT (A1)", "----0000-110------------1011----")
|
||||||
INST(arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv") // v4
|
INST(arm_LDR_lit, "LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv")
|
||||||
INST(arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm") // v4
|
INST(arm_LDRB_lit, "LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv")
|
||||||
INST(arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv") // v1
|
INST(arm_PKHBT, "PKHBT", "cccc01101000nnnnddddvvvvv001mmmm")
|
||||||
INST(arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm") // v1
|
INST(arm_PKHTB, "PKHTB", "cccc01101000nnnnddddvvvvv101mmmm")
|
||||||
INST(arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv") // v1
|
INST(arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn")
|
||||||
INST(arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm") // v1
|
INST(arm_SMLAL, "SMLAL", "cccc0000111Sddddaaaammmm1001nnnn")
|
||||||
INST(arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv") // v5E
|
INST(arm_SMULL, "SMULL", "cccc0000110Sddddaaaammmm1001nnnn")
|
||||||
INST(arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm") // v5E
|
INST(arm_UMLAL, "UMLAL", "cccc0000101Sddddaaaammmm1001nnnn")
|
||||||
INST(arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv") // v4
|
INST(arm_UMULL, "UMULL", "cccc0000100Sddddaaaammmm1001nnnn")
|
||||||
INST(arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm") // v4
|
INST(arm_SMLAWy, "SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn")
|
||||||
|
INST(arm_SMMLA, "SMMLA", "cccc01110101ddddaaaammmm00R1nnnn")
|
||||||
// Load/Store Multiple instructions
|
INST(arm_SMMLS, "SMMLS", "cccc01110101ddddaaaammmm11R1nnnn")
|
||||||
INST(arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_SMLAD, "SMLAD", "cccc01110000ddddaaaammmm00M1nnnn")
|
||||||
INST(arm_LDMDA, "LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_SMLALD, "SMLALD", "cccc01110100ddddaaaammmm00M1nnnn")
|
||||||
INST(arm_LDMDB, "LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_SMLSD, "SMLSD", "cccc01110000ddddaaaammmm01M1nnnn")
|
||||||
INST(arm_LDMIB, "LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_SMLSLD, "SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn")
|
||||||
INST(arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------") // v1
|
INST(arm_BFI, "BFI", "cccc0111110vvvvvddddvvvvv001nnnn")
|
||||||
INST(arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------") // v1
|
INST(arm_SBFX, "SBFX", "cccc0111101wwwwwddddvvvvv101nnnn")
|
||||||
INST(arm_STM, "STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_UBFX, "UBFX", "cccc0111111wwwwwddddvvvvv101nnnn")
|
||||||
INST(arm_STMDA, "STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_SMLALxy, "SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn")
|
||||||
INST(arm_STMDB, "STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_SMLAxy, "SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn")
|
||||||
INST(arm_STMIB, "STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx") // v1
|
INST(arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_STM_usr, "STM (usr reg)", "----100--100--------------------") // v1
|
INST(arm_ADD_rsr, "ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm")
|
||||||
|
INST(arm_AND_rsr, "AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm")
|
||||||
// Miscellaneous instructions
|
INST(arm_BIC_rsr, "BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_BFC, "BFC", "cccc0111110vvvvvddddvvvvv0011111") // v6T2
|
INST(arm_EOR_rsr, "EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_BFI, "BFI", "cccc0111110vvvvvddddvvvvv001nnnn") // v6T2
|
INST(arm_ORR_rsr, "ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_CLZ, "CLZ", "cccc000101101111dddd11110001mmmm") // v5
|
INST(arm_RSB_rsr, "RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_MOVT, "MOVT", "cccc00110100vvvvddddvvvvvvvvvvvv") // v6T2
|
INST(arm_RSC_rsr, "RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_MOVW, "MOVW", "cccc00110000vvvvddddvvvvvvvvvvvv") // v6T2
|
INST(arm_SBC_rsr, "SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_NOP, "NOP", "----0011001000001111000000000000") // v6K
|
INST(arm_SUB_rsr, "SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm")
|
||||||
INST(arm_SBFX, "SBFX", "cccc0111101wwwwwddddvvvvv101nnnn") // v6T2
|
INST(arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv")
|
||||||
INST(arm_SEL, "SEL", "cccc01101000nnnndddd11111011mmmm") // v6
|
INST(arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv")
|
||||||
INST(arm_UBFX, "UBFX", "cccc0111111wwwwwddddvvvvv101nnnn") // v6T2
|
INST(arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv")
|
||||||
|
INST(arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv")
|
||||||
// Unsigned Sum of Absolute Differences instructions
|
INST(arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv")
|
||||||
INST(arm_USAD8, "USAD8", "cccc01111000dddd1111mmmm0001nnnn") // v6
|
INST(arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv")
|
||||||
INST(arm_USADA8, "USADA8", "cccc01111000ddddaaaammmm0001nnnn") // v6
|
INST(arm_SSAT, "SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn")
|
||||||
|
INST(arm_USAT, "USAT", "cccc0110111vvvvvddddvvvvvr01nnnn")
|
||||||
// Packing instructions
|
INST(arm_MCRR, "MCRR", "cccc11000100uuuuttttppppooooMMMM")
|
||||||
INST(arm_PKHBT, "PKHBT", "cccc01101000nnnnddddvvvvv001mmmm") // v6K
|
INST(arm_MRRC, "MRRC", "cccc11000101uuuuttttppppooooMMMM")
|
||||||
INST(arm_PKHTB, "PKHTB", "cccc01101000nnnnddddvvvvv101mmmm") // v6K
|
INST(arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm")
|
||||||
|
INST(arm_ADD_reg, "ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm")
|
||||||
// Reversal instructions
|
INST(arm_AND_reg, "AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm")
|
||||||
INST(arm_RBIT, "RBIT", "cccc011011111111dddd11110011mmmm") // v6T2
|
INST(arm_BIC_reg, "BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm")
|
||||||
INST(arm_REV, "REV", "cccc011010111111dddd11110011mmmm") // v6
|
INST(arm_EOR_reg, "EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm")
|
||||||
INST(arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm") // v6
|
INST(arm_ORR_reg, "ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm")
|
||||||
INST(arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm") // v6
|
INST(arm_RSB_reg, "RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm")
|
||||||
|
INST(arm_RSC_reg, "RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm")
|
||||||
// Saturation instructions
|
INST(arm_SBC_reg, "SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm")
|
||||||
INST(arm_SSAT, "SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn") // v6
|
INST(arm_SUB_reg, "SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm")
|
||||||
INST(arm_SSAT16, "SSAT16", "cccc01101010vvvvdddd11110011nnnn") // v6
|
INST(arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----")
|
||||||
INST(arm_USAT, "USAT", "cccc0110111vvvvvddddvvvvvr01nnnn") // v6
|
INST(arm_LDRT, "LDRT (A2)", "----0110-011---------------0----")
|
||||||
INST(arm_USAT16, "USAT16", "cccc01101110vvvvdddd11110011nnnn") // v6
|
INST(arm_STRBT, "STRBT (A2)", "----0110-110---------------0----")
|
||||||
|
INST(arm_STRT, "STRT (A2)", "----0110-010---------------0----")
|
||||||
// Divide instructions
|
INST(arm_MOVT, "MOVT", "cccc00110100vvvvddddvvvvvvvvvvvv")
|
||||||
INST(arm_SDIV, "SDIV", "cccc01110001dddd1111mmmm0001nnnn") // v7a
|
INST(arm_MOVW, "MOVW", "cccc00110000vvvvddddvvvvvvvvvvvv")
|
||||||
INST(arm_UDIV, "UDIV", "cccc01110011dddd1111mmmm0001nnnn") // v7a
|
INST(arm_BLX_imm, "BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv")
|
||||||
|
INST(arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv")
|
||||||
// Multiply (Normal) instructions
|
INST(arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv")
|
||||||
INST(arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn") // v2
|
INST(arm_AND_imm, "AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv")
|
||||||
INST(arm_MLS, "MLS", "cccc00000110ddddaaaammmm1001nnnn") // v6T2
|
INST(arm_BIC_imm, "BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv")
|
||||||
INST(arm_MUL, "MUL", "cccc0000000Sdddd0000mmmm1001nnnn") // v2
|
INST(arm_EOR_imm, "EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv")
|
||||||
|
INST(arm_ORR_imm, "ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv")
|
||||||
// Multiply (Long) instructions
|
INST(arm_RSB_imm, "RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv")
|
||||||
INST(arm_SMLAL, "SMLAL", "cccc0000111Sddddaaaammmm1001nnnn") // v3M
|
INST(arm_RSC_imm, "RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv")
|
||||||
INST(arm_SMULL, "SMULL", "cccc0000110Sddddaaaammmm1001nnnn") // v3M
|
INST(arm_SBC_imm, "SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv")
|
||||||
INST(arm_UMAAL, "UMAAL", "cccc00000100ddddaaaammmm1001nnnn") // v6
|
INST(arm_SUB_imm, "SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv")
|
||||||
INST(arm_UMLAL, "UMLAL", "cccc0000101Sddddaaaammmm1001nnnn") // v3M
|
INST(arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------")
|
||||||
INST(arm_UMULL, "UMULL", "cccc0000100Sddddaaaammmm1001nnnn") // v3M
|
INST(arm_LDRT, "LDRT (A1)", "----0100-011--------------------")
|
||||||
|
INST(arm_STRBT, "STRBT (A1)", "----0100-110--------------------")
|
||||||
// Multiply (Halfword) instructions
|
INST(arm_STRT, "STRT (A1)", "----0100-010--------------------")
|
||||||
INST(arm_SMLALxy, "SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn") // v5xP
|
INST(arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx")
|
||||||
INST(arm_SMLAxy, "SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn") // v5xP
|
INST(arm_LDMDA, "LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx")
|
||||||
INST(arm_SMULxy, "SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn") // v5xP
|
INST(arm_LDMDB, "LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx")
|
||||||
|
INST(arm_LDMIB, "LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx")
|
||||||
// Multiply (Word by Halfword) instructions
|
INST(arm_STM, "STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx")
|
||||||
INST(arm_SMLAWy, "SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn") // v5xP
|
INST(arm_STMDA, "STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx")
|
||||||
INST(arm_SMULWy, "SMULWY", "cccc00010010dddd0000mmmm1y10nnnn") // v5xP
|
INST(arm_STMDB, "STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx")
|
||||||
|
INST(arm_STMIB, "STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx")
|
||||||
// Multiply (Most Significant Word) instructions
|
INST(arm_MCR, "MCR", "cccc1110ooo0NNNNttttppppooo1MMMM")
|
||||||
INST(arm_SMMUL, "SMMUL", "cccc01110101dddd1111mmmm00R1nnnn") // v6
|
INST(arm_MRC, "MRC", "cccc1110ooo1NNNNttttppppooo1MMMM")
|
||||||
INST(arm_SMMLA, "SMMLA", "cccc01110101ddddaaaammmm00R1nnnn") // v6
|
INST(arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm")
|
||||||
INST(arm_SMMLS, "SMMLS", "cccc01110101ddddaaaammmm11R1nnnn") // v6
|
INST(arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm")
|
||||||
|
INST(arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm")
|
||||||
// Multiply (Dual) instructions
|
INST(arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm")
|
||||||
INST(arm_SMLAD, "SMLAD", "cccc01110000ddddaaaammmm00M1nnnn") // v6
|
INST(arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------")
|
||||||
INST(arm_SMLALD, "SMLALD", "cccc01110100ddddaaaammmm00M1nnnn") // v6
|
INST(arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------")
|
||||||
INST(arm_SMLSD, "SMLSD", "cccc01110000ddddaaaammmm01M1nnnn") // v6
|
INST(arm_STM_usr, "STM (usr reg)", "----100--100--------------------")
|
||||||
INST(arm_SMLSLD, "SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn") // v6
|
INST(arm_CDP, "CDP", "cccc1110ooooNNNNDDDDppppooo0MMMM")
|
||||||
INST(arm_SMUAD, "SMUAD", "cccc01110000dddd1111mmmm00M1nnnn") // v6
|
INST(arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv")
|
||||||
INST(arm_SMUSD, "SMUSD", "cccc01110000dddd1111mmmm01M1nnnn") // v6
|
INST(arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv")
|
||||||
|
INST(arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv")
|
||||||
// Parallel Add/Subtract (Modulo) instructions
|
INST(arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv")
|
||||||
INST(arm_SADD8, "SADD8", "cccc01100001nnnndddd11111001mmmm") // v6
|
INST(arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv")
|
||||||
INST(arm_SADD16, "SADD16", "cccc01100001nnnndddd11110001mmmm") // v6
|
INST(arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv")
|
||||||
INST(arm_SASX, "SASX", "cccc01100001nnnndddd11110011mmmm") // v6
|
INST(arm_LDC, "LDC", "cccc110pudw1nnnnDDDDppppvvvvvvvv")
|
||||||
INST(arm_SSAX, "SSAX", "cccc01100001nnnndddd11110101mmmm") // v6
|
INST(arm_STC, "STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv")
|
||||||
INST(arm_SSUB8, "SSUB8", "cccc01100001nnnndddd11111111mmmm") // v6
|
INST(arm_SVC, "SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv")
|
||||||
INST(arm_SSUB16, "SSUB16", "cccc01100001nnnndddd11110111mmmm") // v6
|
|
||||||
INST(arm_UADD8, "UADD8", "cccc01100101nnnndddd11111001mmmm") // v6
|
|
||||||
INST(arm_UADD16, "UADD16", "cccc01100101nnnndddd11110001mmmm") // v6
|
|
||||||
INST(arm_UASX, "UASX", "cccc01100101nnnndddd11110011mmmm") // v6
|
|
||||||
INST(arm_USAX, "USAX", "cccc01100101nnnndddd11110101mmmm") // v6
|
|
||||||
INST(arm_USUB8, "USUB8", "cccc01100101nnnndddd11111111mmmm") // v6
|
|
||||||
INST(arm_USUB16, "USUB16", "cccc01100101nnnndddd11110111mmmm") // v6
|
|
||||||
|
|
||||||
// Parallel Add/Subtract (Saturating) instructions
|
|
||||||
INST(arm_QADD8, "QADD8", "cccc01100010nnnndddd11111001mmmm") // v6
|
|
||||||
INST(arm_QADD16, "QADD16", "cccc01100010nnnndddd11110001mmmm") // v6
|
|
||||||
INST(arm_QASX, "QASX", "cccc01100010nnnndddd11110011mmmm") // v6
|
|
||||||
INST(arm_QSAX, "QSAX", "cccc01100010nnnndddd11110101mmmm") // v6
|
|
||||||
INST(arm_QSUB8, "QSUB8", "cccc01100010nnnndddd11111111mmmm") // v6
|
|
||||||
INST(arm_QSUB16, "QSUB16", "cccc01100010nnnndddd11110111mmmm") // v6
|
|
||||||
INST(arm_UQADD8, "UQADD8", "cccc01100110nnnndddd11111001mmmm") // v6
|
|
||||||
INST(arm_UQADD16, "UQADD16", "cccc01100110nnnndddd11110001mmmm") // v6
|
|
||||||
INST(arm_UQASX, "UQASX", "cccc01100110nnnndddd11110011mmmm") // v6
|
|
||||||
INST(arm_UQSAX, "UQSAX", "cccc01100110nnnndddd11110101mmmm") // v6
|
|
||||||
INST(arm_UQSUB8, "UQSUB8", "cccc01100110nnnndddd11111111mmmm") // v6
|
|
||||||
INST(arm_UQSUB16, "UQSUB16", "cccc01100110nnnndddd11110111mmmm") // v6
|
|
||||||
|
|
||||||
// Parallel Add/Subtract (Halving) instructions
|
|
||||||
INST(arm_SHADD8, "SHADD8", "cccc01100011nnnndddd11111001mmmm") // v6
|
|
||||||
INST(arm_SHADD16, "SHADD16", "cccc01100011nnnndddd11110001mmmm") // v6
|
|
||||||
INST(arm_SHASX, "SHASX", "cccc01100011nnnndddd11110011mmmm") // v6
|
|
||||||
INST(arm_SHSAX, "SHSAX", "cccc01100011nnnndddd11110101mmmm") // v6
|
|
||||||
INST(arm_SHSUB8, "SHSUB8", "cccc01100011nnnndddd11111111mmmm") // v6
|
|
||||||
INST(arm_SHSUB16, "SHSUB16", "cccc01100011nnnndddd11110111mmmm") // v6
|
|
||||||
INST(arm_UHADD8, "UHADD8", "cccc01100111nnnndddd11111001mmmm") // v6
|
|
||||||
INST(arm_UHADD16, "UHADD16", "cccc01100111nnnndddd11110001mmmm") // v6
|
|
||||||
INST(arm_UHASX, "UHASX", "cccc01100111nnnndddd11110011mmmm") // v6
|
|
||||||
INST(arm_UHSAX, "UHSAX", "cccc01100111nnnndddd11110101mmmm") // v6
|
|
||||||
INST(arm_UHSUB8, "UHSUB8", "cccc01100111nnnndddd11111111mmmm") // v6
|
|
||||||
INST(arm_UHSUB16, "UHSUB16", "cccc01100111nnnndddd11110111mmmm") // v6
|
|
||||||
|
|
||||||
// Saturated Add/Subtract instructions
|
|
||||||
INST(arm_QADD, "QADD", "cccc00010000nnnndddd00000101mmmm") // v5xP
|
|
||||||
INST(arm_QSUB, "QSUB", "cccc00010010nnnndddd00000101mmmm") // v5xP
|
|
||||||
INST(arm_QDADD, "QDADD", "cccc00010100nnnndddd00000101mmmm") // v5xP
|
|
||||||
INST(arm_QDSUB, "QDSUB", "cccc00010110nnnndddd00000101mmmm") // v5xP
|
|
||||||
|
|
||||||
// Status Register Access instructions
|
|
||||||
INST(arm_CPS, "CPS", "111100010000---00000000---0-----") // v6
|
|
||||||
INST(arm_SETEND, "SETEND", "1111000100000001000000e000000000") // v6
|
|
||||||
INST(arm_MRS, "MRS", "cccc000100001111dddd000000000000") // v3
|
|
||||||
INST(arm_MSR_imm, "MSR (imm)", "cccc00110010mmmm1111rrrrvvvvvvvv") // v3
|
|
||||||
INST(arm_MSR_reg, "MSR (reg)", "cccc00010010mmmm111100000000nnnn") // v3
|
|
||||||
INST(arm_RFE, "RFE", "1111100--0-1----0000101000000000") // v6
|
|
||||||
INST(arm_SRS, "SRS", "1111100--1-0110100000101000-----") // v6
|
|
||||||
|
|
@ -27,50 +27,12 @@ template<typename Visitor>
|
||||||
using ASIMDMatcher = Decoder::Matcher<Visitor, u32>;
|
using ASIMDMatcher = Decoder::Matcher<Visitor, u32>;
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::vector<ASIMDMatcher<V>> GetASIMDDecodeTable() noexcept {
|
static std::optional<std::reference_wrapper<const ASIMDMatcher<V>>> DecodeASIMD(u32 instruction) noexcept {
|
||||||
std::vector<std::pair<const char*, ASIMDMatcher<V>>> table = {
|
alignas(64) static const auto table = std::array{
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(ASIMDMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(ASIMDMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||||
#include "./asimd.inc"
|
#include "./asimd.inc"
|
||||||
#undef INST
|
#undef INST
|
||||||
};
|
};
|
||||||
// Exceptions to the rule of thumb.
|
|
||||||
const std::set<std::string> comes_first{
|
|
||||||
"VBIC, VMOV, VMVN, VORR (immediate)",
|
|
||||||
"VEXT",
|
|
||||||
"VTBL",
|
|
||||||
"VTBX",
|
|
||||||
"VDUP (scalar)",
|
|
||||||
};
|
|
||||||
const std::set<std::string> comes_last{
|
|
||||||
"VMLA (scalar)",
|
|
||||||
"VMLAL (scalar)",
|
|
||||||
"VQDMLAL/VQDMLSL (scalar)",
|
|
||||||
"VMUL (scalar)",
|
|
||||||
"VMULL (scalar)",
|
|
||||||
"VQDMULL (scalar)",
|
|
||||||
"VQDMULH (scalar)",
|
|
||||||
"VQRDMULH (scalar)",
|
|
||||||
};
|
|
||||||
const auto sort_begin = std::stable_partition(table.begin(), table.end(), [&](const auto& e) {
|
|
||||||
return comes_first.count(e.first) > 0;
|
|
||||||
});
|
|
||||||
const auto sort_end = std::stable_partition(table.begin(), table.end(), [&](const auto& e) {
|
|
||||||
return comes_last.count(e.first) == 0;
|
|
||||||
});
|
|
||||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
|
||||||
std::stable_sort(sort_begin, sort_end, [](const auto& a, const auto& b) {
|
|
||||||
return mcl::bit::count_ones(a.second.GetMask()) > mcl::bit::count_ones(b.second.GetMask());
|
|
||||||
});
|
|
||||||
std::vector<ASIMDMatcher<V>> final_table;
|
|
||||||
std::transform(table.cbegin(), table.cend(), std::back_inserter(final_table), [](auto const& e) {
|
|
||||||
return e.second;
|
|
||||||
});
|
|
||||||
return final_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
std::optional<std::reference_wrapper<const ASIMDMatcher<V>>> DecodeASIMD(u32 instruction) noexcept {
|
|
||||||
alignas(64) static const auto table = GetASIMDDecodeTable<V>();
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), [instruction](const auto& matcher) {
|
auto iter = std::find_if(table.begin(), table.end(), [instruction](const auto& matcher) {
|
||||||
return matcher.Matches(instruction);
|
return matcher.Matches(instruction);
|
||||||
});
|
});
|
||||||
|
|
@ -78,7 +40,7 @@ std::optional<std::reference_wrapper<const ASIMDMatcher<V>>> DecodeASIMD(u32 ins
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::string_view> GetNameASIMD(u32 inst) noexcept {
|
static std::optional<std::string_view> GetNameASIMD(u32 inst) noexcept {
|
||||||
std::vector<std::pair<std::string_view, ASIMDMatcher<V>>> list = {
|
std::vector<std::pair<std::string_view, ASIMDMatcher<V>>> list = {
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(ASIMDMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(ASIMDMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
||||||
#include "./asimd.inc"
|
#include "./asimd.inc"
|
||||||
|
|
|
||||||
|
|
@ -1,172 +1,151 @@
|
||||||
// Three registers of the same length
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
INST(asimd_VHADD, "VHADD", "1111001U0Dzznnnndddd0000NQM0mmmm") // ASIMD
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
INST(asimd_VQADD, "VQADD", "1111001U0Dzznnnndddd0000NQM1mmmm") // ASIMD
|
// DO NOT REORDER
|
||||||
INST(asimd_VRHADD, "VRHADD", "1111001U0Dzznnnndddd0001NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VAND_reg, "VAND (register)", "111100100D00nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VBIC_reg, "VBIC (register)", "111100100D01nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VORR_reg, "VORR (register)", "111100100D10nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VORN_reg, "VORN (register)", "111100100D11nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VEOR_reg, "VEOR (register)", "111100110D00nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VBSL, "VBSL", "111100110D01nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VBIT, "VBIT", "111100110D10nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VBIF, "VBIF", "111100110D11nnnndddd0001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VHSUB, "VHSUB", "1111001U0Dzznnnndddd0010NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VQSUB, "VQSUB", "1111001U0Dzznnnndddd0010NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VCGT_reg, "VCGT (register)", "1111001U0Dzznnnndddd0011NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VCGE_reg, "VCGE (register)", "1111001U0Dzznnnndddd0011NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VSHL_reg, "VSHL (register)", "1111001U0Dzznnnndddd0100NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VQSHL_reg, "VQSHL (register)", "1111001U0Dzznnnndddd0100NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VRSHL, "VRSHL", "1111001U0Dzznnnndddd0101NQM0mmmm") // ASIMD
|
|
||||||
//INST(asimd_VQRSHL, "VQRSHL", "1111001U0-CC--------0101---1----") // ASIMD
|
|
||||||
INST(asimd_VMAX, "VMAX/VMIN (integer)", "1111001U0Dzznnnnmmmm0110NQMommmm") // ASIMD
|
|
||||||
INST(asimd_VABD, "VABD", "1111001U0Dzznnnndddd0111NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VABA, "VABA", "1111001U0Dzznnnndddd0111NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VADD_int, "VADD (integer)", "111100100Dzznnnndddd1000NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VSUB_int, "VSUB (integer)", "111100110Dzznnnndddd1000NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VTST, "VTST", "111100100Dzznnnndddd1000NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VCEQ_reg, "VCEG (register)", "111100110Dzznnnndddd1000NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VMLA, "VMLA/VMLS", "1111001o0Dzznnnndddd1001NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VMUL, "VMUL", "1111001P0Dzznnnndddd1001NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VPMAX_int, "VPMAX/VPMIN (integer)", "1111001U0Dzznnnndddd1010NQMommmm") // ASIMD
|
|
||||||
INST(v8_VMAXNM, "VMAXNM", "111100110D0znnnndddd1111NQM1mmmm") // v8
|
|
||||||
INST(v8_VMINNM, "VMINNM", "111100110D1znnnndddd1111NQM1mmmm") // v8
|
|
||||||
INST(asimd_VQDMULH, "VQDMULH", "111100100Dzznnnndddd1011NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VQRDMULH, "VQRDMULH", "111100110Dzznnnndddd1011NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VPADD, "VPADD", "111100100Dzznnnndddd1011NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VFMA, "VFMA", "111100100D0znnnndddd1100NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VFMS, "VFMS", "111100100D1znnnndddd1100NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VADD_float, "VADD (floating-point)", "111100100D0znnnndddd1101NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VSUB_float, "VSUB (floating-point)", "111100100D1znnnndddd1101NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VPADD_float, "VPADD (floating-point)", "111100110D0znnnndddd1101NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VABD_float, "VABD (floating-point)", "111100110D1znnnndddd1101NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VMLA_float, "VMLA (floating-point)", "111100100D0znnnndddd1101NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VMLS_float, "VMLS (floating-point)", "111100100D1znnnndddd1101NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VMUL_float, "VMUL (floating-point)", "111100110D0znnnndddd1101NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VCEQ_reg_float, "VCEQ (register)", "111100100D0znnnndddd1110NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VCGE_reg_float, "VCGE (register)", "111100110D0znnnndddd1110NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VCGT_reg_float, "VCGT (register)", "111100110D1znnnndddd1110NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VACGE, "VACGE", "111100110Doznnnndddd1110NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VMAX_float, "VMAX (floating-point)", "111100100D0znnnndddd1111NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VMIN_float, "VMIN (floating-point)", "111100100D1znnnndddd1111NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VPMAX_float, "VPMAX (floating-point)", "111100110D0znnnndddd1111NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VPMIN_float, "VPMIN (floating-point)", "111100110D1znnnndddd1111NQM0mmmm") // ASIMD
|
|
||||||
INST(asimd_VRECPS, "VRECPS", "111100100D0znnnndddd1111NQM1mmmm") // ASIMD
|
|
||||||
INST(asimd_VRSQRTS, "VRSQRTS", "111100100D1znnnndddd1111NQM1mmmm") // ASIMD
|
|
||||||
INST(v8_SHA256H, "SHA256H", "111100110D00nnnndddd1100NQM0mmmm") // v8
|
|
||||||
INST(v8_SHA256H2, "SHA256H2", "111100110D01nnnndddd1100NQM0mmmm") // v8
|
|
||||||
INST(v8_SHA256SU1, "SHA256SU1", "111100110D10nnnndddd1100NQM0mmmm") // v8
|
|
||||||
|
|
||||||
// Three registers of different lengths
|
INST(asimd_VMOV_imm, "VBIC, VMOV, VMVN, VORR (immediate)", "1111001a1D000bcdVVVVmmmm0Qo1efgh")
|
||||||
INST(asimd_VADDL, "VADDL/VADDW", "1111001U1Dzznnnndddd000oN0M0mmmm") // ASIMD
|
INST(asimd_VEXT, "VEXT", "111100101D11nnnnddddiiiiNQM0mmmm")
|
||||||
INST(asimd_VSUBL, "VSUBL/VSUBW", "1111001U1Dzznnnndddd001oN0M0mmmm") // ASIMD
|
INST(asimd_VTBL, "VTBL", "111100111D11nnnndddd10zzN0M0mmmm")
|
||||||
//INST(asimd_VADDHN, "VADDHN", "111100101-----------0100-0-0----") // ASIMD
|
INST(asimd_VTBX, "VTBX", "111100111D11nnnndddd10zzN1M0mmmm")
|
||||||
//INST(asimd_VRADDHN, "VRADDHN", "111100111-----------0100-0-0----") // ASIMD
|
INST(asimd_VDUP_scalar, "VDUP (scalar)", "111100111D11iiiidddd11000QM0mmmm")
|
||||||
INST(asimd_VABAL, "VABAL", "1111001U1Dzznnnndddd0101N0M0mmmm") // ASIMD
|
INST(asimd_VSWP, "VSWP", "111100111D110010dddd00000QM0mmmm")
|
||||||
//INST(asimd_VSUBHN, "VSUBHN", "111100101-----------0110-0-0----") // ASIMD
|
INST(asimd_VMOVN, "VMOVN", "111100111D11zz10dddd001000M0mmmm")
|
||||||
//INST(asimd_VRSUBHN, "VRSUBHN", "111100111-----------0110-0-0----") // ASIMD
|
INST(asimd_VQMOVUN, "VQMOVUN", "111100111D11zz10dddd001001M0mmmm")
|
||||||
INST(asimd_VABDL, "VABDL", "1111001U1Dzznnnndddd0111N0M0mmmm") // ASIMD
|
INST(asimd_VSHLL_max, "VSHLL_max", "111100111D11zz10dddd001100M0mmmm")
|
||||||
INST(asimd_VMLAL, "VMLAL/VMLSL", "1111001U1Dzznnnndddd10o0N0M0mmmm") // ASIMD
|
INST(v8_AESE, "AESE", "111100111D11zz00dddd001100M0mmmm")
|
||||||
//INST(asimd_VQDMLAL, "VQDMLAL", "111100101-----------10-1-0-0----") // ASIMD
|
INST(v8_AESD, "AESD", "111100111D11zz00dddd001101M0mmmm")
|
||||||
INST(asimd_VMULL, "VMULL", "1111001U1Dzznnnndddd11P0N0M0mmmm") // ASIMD
|
INST(v8_AESMC, "AESMC", "111100111D11zz00dddd001110M0mmmm")
|
||||||
//INST(asimd_VQDMULL, "VQDMULL", "111100101-----------1101-0-0----") // ASIMD
|
INST(v8_AESIMC, "AESIMC", "111100111D11zz00dddd001111M0mmmm")
|
||||||
|
INST(arm_UDF, "UNALLOCATED", "111100111-11--01----001010-0----")
|
||||||
// Two registers and a scalar
|
INST(arm_UDF, "UNALLOCATED (SHA1H)", "111100111-11--01----001011-0----")
|
||||||
INST(asimd_VMLA_scalar, "VMLA (scalar)", "1111001Q1Dzznnnndddd0o0FN1M0mmmm") // ASIMD
|
INST(arm_UDF, "UNALLOCATED (SHA1SU1)", "111100111-11--10----001110-0----")
|
||||||
INST(asimd_VMLAL_scalar, "VMLAL (scalar)", "1111001U1dzznnnndddd0o10N1M0mmmm") // ASIMD
|
INST(v8_SHA256SU0, "SHA256SU0", "111100111D11zz10dddd001111M0mmmm")
|
||||||
//INST(asimd_VQDMLAL_scalar, "VQDMLAL/VQDMLSL (scalar)", "111100101-BB--------0x11-1-0----") // ASIMD
|
INST(asimd_VCLS, "VCLS", "111100111D11zz00dddd01000QM0mmmm")
|
||||||
INST(asimd_VMUL_scalar, "VMUL (scalar)", "1111001Q1Dzznnnndddd100FN1M0mmmm") // ASIMD
|
INST(asimd_VCLZ, "VCLZ", "111100111D11zz00dddd01001QM0mmmm")
|
||||||
INST(asimd_VMULL_scalar, "VMULL (scalar)", "1111001U1Dzznnnndddd1010N1M0mmmm") // ASIMD
|
INST(asimd_VCNT, "VCNT", "111100111D11zz00dddd01010QM0mmmm")
|
||||||
INST(asimd_VQDMULL_scalar, "VQDMULL (scalar)", "111100101Dzznnnndddd1011N1M0mmmm") // ASIMD
|
INST(asimd_VMVN_reg, "VMVN_reg", "111100111D11zz00dddd01011QM0mmmm")
|
||||||
INST(asimd_VQDMULH_scalar, "VQDMULH (scalar)", "1111001Q1Dzznnnndddd1100N1M0mmmm") // ASIMD
|
INST(asimd_VQABS, "VQABS", "111100111D11zz00dddd01110QM0mmmm")
|
||||||
INST(asimd_VQRDMULH_scalar, "VQRDMULH (scalar)", "1111001Q1Dzznnnndddd1101N1M0mmmm") // ASIMD
|
INST(asimd_VQNEG, "VQNEG", "111100111D11zz00dddd01111QM0mmmm")
|
||||||
|
INST(arm_UDF, "UNALLOCATED", "111100111-11--01----01101--0----")
|
||||||
// Two registers and a shift amount
|
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----00000--0----")
|
||||||
INST(asimd_SHR, "SHR", "1111001U1Diiiiiidddd0000LQM1mmmm") // ASIMD
|
INST(asimd_VTRN, "VTRN", "111100111D11zz10dddd00001QM0mmmm")
|
||||||
INST(asimd_SRA, "SRA", "1111001U1Diiiiiidddd0001LQM1mmmm") // ASIMD
|
INST(asimd_VUZP, "VUZP", "111100111D11zz10dddd00010QM0mmmm")
|
||||||
INST(asimd_VRSHR, "VRSHR", "1111001U1Diiiiiidddd0010LQM1mmmm") // ASIMD
|
INST(asimd_VZIP, "VZIP", "111100111D11zz10dddd00011QM0mmmm")
|
||||||
INST(asimd_VRSRA, "VRSRA", "1111001U1Diiiiiidddd0011LQM1mmmm") // ASIMD
|
INST(asimd_VQMOVN, "VQMOVN", "111100111D11zz10dddd00101oM0mmmm")
|
||||||
INST(asimd_VSRI, "VSRI", "111100111Diiiiiidddd0100LQM1mmmm") // ASIMD
|
INST(v8_VRINTN, "VRINTN", "111100111D11zz10dddd01000QM0mmmm")
|
||||||
INST(asimd_VSHL, "VSHL", "111100101Diiiiiidddd0101LQM1mmmm") // ASIMD
|
INST(v8_VRINTX, "VRINTX", "111100111D11zz10dddd01001QM0mmmm")
|
||||||
INST(asimd_VSLI, "VSLI", "111100111Diiiiiidddd0101LQM1mmmm") // ASIMD
|
INST(v8_VRINTA, "VRINTA", "111100111D11zz10dddd01010QM0mmmm")
|
||||||
INST(asimd_VQSHL, "VQSHL" , "1111001U1Diiiiiidddd011oLQM1mmmm") // ASIMD
|
INST(v8_VRINTZ, "VRINTZ", "111100111D11zz10dddd01011QM0mmmm")
|
||||||
INST(asimd_VSHRN, "VSHRN", "111100101Diiiiiidddd100000M1mmmm") // ASIMD
|
INST(v8_VRINTM, "VRINTM", "111100111D11zz10dddd01101QM0mmmm")
|
||||||
INST(asimd_VRSHRN, "VRSHRN", "111100101Diiiiiidddd100001M1mmmm") // ASIMD
|
INST(v8_VRINTP, "VRINTP", "111100111D11zz10dddd01111QM0mmmm")
|
||||||
INST(asimd_VQSHRUN, "VQSHRUN", "111100111Diiiiiidddd100000M1mmmm") // ASIMD
|
INST(asimd_VCVT_half, "VCVT (half-precision)", "111100111D11zz10dddd011o00M0mmmm")
|
||||||
INST(asimd_VQRSHRUN, "VQRSHRUN", "111100111Diiiiiidddd100001M1mmmm") // ASIMD
|
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----011-01-0----")
|
||||||
INST(asimd_VQSHRN, "VQSHRN", "1111001U1Diiiiiidddd100100M1mmmm") // ASIMD
|
INST(asimd_VPADDL, "VPADDL", "111100111D11zz00dddd0010oQM0mmmm")
|
||||||
INST(asimd_VQRSHRN, "VQRSHRN", "1111001U1Diiiiiidddd100101M1mmmm") // ASIMD
|
INST(asimd_VPADAL, "VPADAL", "111100111D11zz00dddd0110oQM0mmmm")
|
||||||
INST(asimd_VSHLL, "VSHLL", "1111001U1Diiiiiidddd101000M1mmmm") // ASIMD
|
INST(asimd_VCGT_zero, "VCGT (zero)", "111100111D11zz01dddd0F000QM0mmmm")
|
||||||
INST(asimd_VCVT_fixed, "VCVT (fixed-point)", "1111001U1Diiiiiidddd111o0QM1mmmm") // ASIMD
|
INST(asimd_VCGE_zero, "VCGE (zero)", "111100111D11zz01dddd0F001QM0mmmm")
|
||||||
|
INST(asimd_VCEQ_zero, "VCEQ (zero)", "111100111D11zz01dddd0F010QM0mmmm")
|
||||||
// Two registers, miscellaneous
|
INST(asimd_VCLE_zero, "VCLE (zero)", "111100111D11zz01dddd0F011QM0mmmm")
|
||||||
INST(asimd_VREV, "VREV{16,32,64}", "111100111D11zz00dddd000ooQM0mmmm") // ASIMD
|
INST(asimd_VCLT_zero, "VCLT (zero)", "111100111D11zz01dddd0F100QM0mmmm")
|
||||||
INST(asimd_VPADDL, "VPADDL", "111100111D11zz00dddd0010oQM0mmmm") // ASIMD
|
INST(asimd_VABS, "VABS", "111100111D11zz01dddd0F110QM0mmmm")
|
||||||
INST(asimd_VCLS, "VCLS", "111100111D11zz00dddd01000QM0mmmm") // ASIMD
|
INST(asimd_VNEG, "VNEG", "111100111D11zz01dddd0F111QM0mmmm")
|
||||||
INST(asimd_VCLZ, "VCLZ", "111100111D11zz00dddd01001QM0mmmm") // ASIMD
|
INST(v8_VCVTA, "VCVTA", "111100111D11zz11dddd0000oQM0mmmm")
|
||||||
INST(asimd_VCNT, "VCNT", "111100111D11zz00dddd01010QM0mmmm") // ASIMD
|
INST(v8_VCVTN, "VCVTN", "111100111D11zz11dddd0001oQM0mmmm")
|
||||||
INST(asimd_VMVN_reg, "VMVN_reg", "111100111D11zz00dddd01011QM0mmmm") // ASIMD
|
INST(v8_VCVTP, "VCVTP", "111100111D11zz11dddd0010oQM0mmmm")
|
||||||
INST(asimd_VPADAL, "VPADAL", "111100111D11zz00dddd0110oQM0mmmm") // ASIMD
|
INST(v8_VCVTM, "VCVTM", "111100111D11zz11dddd0011oQM0mmmm")
|
||||||
INST(asimd_VQABS, "VQABS", "111100111D11zz00dddd01110QM0mmmm") // ASIMD
|
INST(asimd_VRECPE, "VRECPE", "111100111D11zz11dddd010F0QM0mmmm")
|
||||||
INST(asimd_VQNEG, "VQNEG", "111100111D11zz00dddd01111QM0mmmm") // ASIMD
|
INST(asimd_VRSQRTE, "VRSQRTE", "111100111D11zz11dddd010F1QM0mmmm")
|
||||||
INST(asimd_VCGT_zero, "VCGT (zero)", "111100111D11zz01dddd0F000QM0mmmm") // ASIMD
|
INST(asimd_VREV, "VREV{16,32,64}", "111100111D11zz00dddd000ooQM0mmmm")
|
||||||
INST(asimd_VCGE_zero, "VCGE (zero)", "111100111D11zz01dddd0F001QM0mmmm") // ASIMD
|
INST(asimd_VCVT_integer, "VCVT (integer)", "111100111D11zz11dddd011oUQM0mmmm")
|
||||||
INST(asimd_VCEQ_zero, "VCEQ (zero)", "111100111D11zz01dddd0F010QM0mmmm") // ASIMD
|
INST(asimd_VAND_reg, "VAND (register)", "111100100D00nnnndddd0001NQM1mmmm")
|
||||||
INST(asimd_VCLE_zero, "VCLE (zero)", "111100111D11zz01dddd0F011QM0mmmm") // ASIMD
|
INST(asimd_VBIC_reg, "VBIC (register)", "111100100D01nnnndddd0001NQM1mmmm")
|
||||||
INST(asimd_VCLT_zero, "VCLT (zero)", "111100111D11zz01dddd0F100QM0mmmm") // ASIMD
|
INST(asimd_VORR_reg, "VORR (register)", "111100100D10nnnndddd0001NQM1mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--01----01101--0----") // v8
|
INST(asimd_VORN_reg, "VORN (register)", "111100100D11nnnndddd0001NQM1mmmm")
|
||||||
INST(asimd_VABS, "VABS", "111100111D11zz01dddd0F110QM0mmmm") // ASIMD
|
INST(asimd_VEOR_reg, "VEOR (register)", "111100110D00nnnndddd0001NQM1mmmm")
|
||||||
INST(asimd_VNEG, "VNEG", "111100111D11zz01dddd0F111QM0mmmm") // ASIMD
|
INST(asimd_VBSL, "VBSL", "111100110D01nnnndddd0001NQM1mmmm")
|
||||||
INST(asimd_VSWP, "VSWP", "111100111D110010dddd00000QM0mmmm") // ASIMD
|
INST(asimd_VBIT, "VBIT", "111100110D10nnnndddd0001NQM1mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----00000--0----") // ASIMD
|
INST(asimd_VBIF, "VBIF", "111100110D11nnnndddd0001NQM1mmmm")
|
||||||
INST(asimd_VTRN, "VTRN", "111100111D11zz10dddd00001QM0mmmm") // ASIMD
|
INST(v8_SHA256H, "SHA256H", "111100110D00nnnndddd1100NQM0mmmm")
|
||||||
INST(asimd_VUZP, "VUZP", "111100111D11zz10dddd00010QM0mmmm") // ASIMD
|
INST(v8_SHA256H2, "SHA256H2", "111100110D01nnnndddd1100NQM0mmmm")
|
||||||
INST(asimd_VZIP, "VZIP", "111100111D11zz10dddd00011QM0mmmm") // ASIMD
|
INST(v8_SHA256SU1, "SHA256SU1", "111100110D10nnnndddd1100NQM0mmmm")
|
||||||
INST(asimd_VMOVN, "VMOVN", "111100111D11zz10dddd001000M0mmmm") // ASIMD
|
INST(asimd_VSHRN, "VSHRN", "111100101Diiiiiidddd100000M1mmmm")
|
||||||
INST(asimd_VQMOVUN, "VQMOVUN", "111100111D11zz10dddd001001M0mmmm") // ASIMD
|
INST(asimd_VRSHRN, "VRSHRN", "111100101Diiiiiidddd100001M1mmmm")
|
||||||
INST(asimd_VQMOVN, "VQMOVN", "111100111D11zz10dddd00101oM0mmmm") // ASIMD
|
INST(asimd_VQSHRUN, "VQSHRUN", "111100111Diiiiiidddd100000M1mmmm")
|
||||||
INST(asimd_VSHLL_max, "VSHLL_max", "111100111D11zz10dddd001100M0mmmm") // ASIMD
|
INST(asimd_VQRSHRUN, "VQRSHRUN", "111100111Diiiiiidddd100001M1mmmm")
|
||||||
INST(v8_VRINTN, "VRINTN", "111100111D11zz10dddd01000QM0mmmm") // v8
|
INST(v8_VMAXNM, "VMAXNM", "111100110D0znnnndddd1111NQM1mmmm")
|
||||||
INST(v8_VRINTX, "VRINTX", "111100111D11zz10dddd01001QM0mmmm") // v8
|
INST(v8_VMINNM, "VMINNM", "111100110D1znnnndddd1111NQM1mmmm")
|
||||||
INST(v8_VRINTA, "VRINTA", "111100111D11zz10dddd01010QM0mmmm") // v8
|
INST(asimd_VFMA, "VFMA", "111100100D0znnnndddd1100NQM1mmmm")
|
||||||
INST(v8_VRINTZ, "VRINTZ", "111100111D11zz10dddd01011QM0mmmm") // v8
|
INST(asimd_VFMS, "VFMS", "111100100D1znnnndddd1100NQM1mmmm")
|
||||||
INST(v8_VRINTM, "VRINTM", "111100111D11zz10dddd01101QM0mmmm") // v8
|
INST(asimd_VADD_float, "VADD (floating-point)", "111100100D0znnnndddd1101NQM0mmmm")
|
||||||
INST(v8_VRINTP, "VRINTP", "111100111D11zz10dddd01111QM0mmmm") // v8
|
INST(asimd_VSUB_float, "VSUB (floating-point)", "111100100D1znnnndddd1101NQM0mmmm")
|
||||||
INST(asimd_VCVT_half, "VCVT (half-precision)", "111100111D11zz10dddd011o00M0mmmm") // ASIMD
|
INST(asimd_VPADD_float, "VPADD (floating-point)", "111100110D0znnnndddd1101NQM0mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----011-01-0----") // ASIMD
|
INST(asimd_VABD_float, "VABD (floating-point)", "111100110D1znnnndddd1101NQM0mmmm")
|
||||||
INST(v8_VCVTA, "VCVTA", "111100111D11zz11dddd0000oQM0mmmm") // v8
|
INST(asimd_VMLA_float, "VMLA (floating-point)", "111100100D0znnnndddd1101NQM1mmmm")
|
||||||
INST(v8_VCVTN, "VCVTN", "111100111D11zz11dddd0001oQM0mmmm") // v8
|
INST(asimd_VMLS_float, "VMLS (floating-point)", "111100100D1znnnndddd1101NQM1mmmm")
|
||||||
INST(v8_VCVTP, "VCVTP", "111100111D11zz11dddd0010oQM0mmmm") // v8
|
INST(asimd_VMUL_float, "VMUL (floating-point)", "111100110D0znnnndddd1101NQM1mmmm")
|
||||||
INST(v8_VCVTM, "VCVTM", "111100111D11zz11dddd0011oQM0mmmm") // v8
|
INST(asimd_VCEQ_reg_float, "VCEQ (register)", "111100100D0znnnndddd1110NQM0mmmm")
|
||||||
INST(asimd_VRECPE, "VRECPE", "111100111D11zz11dddd010F0QM0mmmm") // ASIMD
|
INST(asimd_VCGE_reg_float, "VCGE (register)", "111100110D0znnnndddd1110NQM0mmmm")
|
||||||
INST(asimd_VRSQRTE, "VRSQRTE", "111100111D11zz11dddd010F1QM0mmmm") // ASIMD
|
INST(asimd_VCGT_reg_float, "VCGT (register)", "111100110D1znnnndddd1110NQM0mmmm")
|
||||||
INST(asimd_VCVT_integer, "VCVT (integer)", "111100111D11zz11dddd011oUQM0mmmm") // ASIMD
|
INST(asimd_VMAX_float, "VMAX (floating-point)", "111100100D0znnnndddd1111NQM0mmmm")
|
||||||
|
INST(asimd_VMIN_float, "VMIN (floating-point)", "111100100D1znnnndddd1111NQM0mmmm")
|
||||||
// Two registers, cryptography
|
INST(asimd_VPMAX_float, "VPMAX (floating-point)", "111100110D0znnnndddd1111NQM0mmmm")
|
||||||
INST(v8_AESE, "AESE", "111100111D11zz00dddd001100M0mmmm") // v8
|
INST(asimd_VPMIN_float, "VPMIN (floating-point)", "111100110D1znnnndddd1111NQM0mmmm")
|
||||||
INST(v8_AESD, "AESD", "111100111D11zz00dddd001101M0mmmm") // v8
|
INST(asimd_VRECPS, "VRECPS", "111100100D0znnnndddd1111NQM1mmmm")
|
||||||
INST(v8_AESMC, "AESMC", "111100111D11zz00dddd001110M0mmmm") // v8
|
INST(asimd_VRSQRTS, "VRSQRTS", "111100100D1znnnndddd1111NQM1mmmm")
|
||||||
INST(v8_AESIMC, "AESIMC", "111100111D11zz00dddd001111M0mmmm") // v8
|
INST(asimd_VQSHRN, "VQSHRN", "1111001U1Diiiiiidddd100100M1mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--01----001010-0----") // v8
|
INST(asimd_VQRSHRN, "VQRSHRN", "1111001U1Diiiiiidddd100101M1mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED (SHA1H)", "111100111-11--01----001011-0----") // v8
|
INST(asimd_VSHLL, "VSHLL", "1111001U1Diiiiiidddd101000M1mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED (SHA1SU1)", "111100111-11--10----001110-0----") // v8
|
INST(asimd_VADD_int, "VADD (integer)", "111100100Dzznnnndddd1000NQM0mmmm")
|
||||||
INST(v8_SHA256SU0, "SHA256SU0", "111100111D11zz10dddd001111M0mmmm") // v8
|
INST(asimd_VSUB_int, "VSUB (integer)", "111100110Dzznnnndddd1000NQM0mmmm")
|
||||||
|
INST(asimd_VTST, "VTST", "111100100Dzznnnndddd1000NQM1mmmm")
|
||||||
// One register and modified immediate
|
INST(asimd_VCEQ_reg, "VCEG (register)", "111100110Dzznnnndddd1000NQM1mmmm")
|
||||||
INST(asimd_VMOV_imm, "VBIC, VMOV, VMVN, VORR (immediate)", "1111001a1D000bcdVVVVmmmm0Qo1efgh") // ASIMD
|
INST(asimd_VQDMULH, "VQDMULH", "111100100Dzznnnndddd1011NQM0mmmm")
|
||||||
|
INST(asimd_VQRDMULH, "VQRDMULH", "111100110Dzznnnndddd1011NQM0mmmm")
|
||||||
// Miscellaneous
|
INST(asimd_VPADD, "VPADD", "111100100Dzznnnndddd1011NQM1mmmm")
|
||||||
INST(asimd_VEXT, "VEXT", "111100101D11nnnnddddiiiiNQM0mmmm") // ASIMD
|
INST(asimd_VACGE, "VACGE", "111100110Doznnnndddd1110NQM1mmmm")
|
||||||
INST(asimd_VTBL, "VTBL", "111100111D11nnnndddd10zzN0M0mmmm") // ASIMD
|
INST(asimd_VABAL, "VABAL", "1111001U1Dzznnnndddd0101N0M0mmmm")
|
||||||
INST(asimd_VTBX, "VTBX", "111100111D11nnnndddd10zzN1M0mmmm") // ASIMD
|
INST(asimd_VABDL, "VABDL", "1111001U1Dzznnnndddd0111N0M0mmmm")
|
||||||
INST(asimd_VDUP_scalar, "VDUP (scalar)", "111100111D11iiiidddd11000QM0mmmm") // ASIMD
|
INST(asimd_VSRI, "VSRI", "111100111Diiiiiidddd0100LQM1mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--------11-----0----") // ASIMD
|
INST(asimd_VSHL, "VSHL", "111100101Diiiiiidddd0101LQM1mmmm")
|
||||||
|
INST(asimd_VSLI, "VSLI", "111100111Diiiiiidddd0101LQM1mmmm")
|
||||||
// Advanced SIMD load/store structures
|
INST(arm_UDF, "UNALLOCATED", "111100111-11--------11-----0----")
|
||||||
INST(v8_VST_multiple, "VST{1-4} (multiple)", "111101000D00nnnnddddxxxxzzaammmm") // v8
|
INST(arm_UDF, "UNALLOCATED", "111101000--0--------1011--------")
|
||||||
INST(v8_VLD_multiple, "VLD{1-4} (multiple)", "111101000D10nnnnddddxxxxzzaammmm") // v8
|
INST(asimd_VHADD, "VHADD", "1111001U0Dzznnnndddd0000NQM0mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111101000--0--------1011--------") // v8
|
INST(asimd_VQADD, "VQADD", "1111001U0Dzznnnndddd0000NQM1mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111101000--0--------11----------") // v8
|
INST(asimd_VRHADD, "VRHADD", "1111001U0Dzznnnndddd0001NQM0mmmm")
|
||||||
INST(arm_UDF, "UNALLOCATED", "111101001-00--------11----------") // v8
|
INST(asimd_VHSUB, "VHSUB", "1111001U0Dzznnnndddd0010NQM0mmmm")
|
||||||
INST(v8_VLD_all_lanes, "VLD{1-4} (all lanes)", "111101001D10nnnndddd11nnzzTammmm") // v8
|
INST(asimd_VQSUB, "VQSUB", "1111001U0Dzznnnndddd0010NQM1mmmm")
|
||||||
INST(v8_VST_single, "VST{1-4} (single)", "111101001D00nnnnddddzzNNaaaammmm") // v8
|
INST(asimd_VCGT_reg, "VCGT (register)", "1111001U0Dzznnnndddd0011NQM0mmmm")
|
||||||
INST(v8_VLD_single, "VLD{1-4} (single)", "111101001D10nnnnddddzzNNaaaammmm") // v8
|
INST(asimd_VCGE_reg, "VCGE (register)", "1111001U0Dzznnnndddd0011NQM1mmmm")
|
||||||
|
INST(asimd_VSHL_reg, "VSHL (register)", "1111001U0Dzznnnndddd0100NQM0mmmm")
|
||||||
|
INST(asimd_VQSHL_reg, "VQSHL (register)", "1111001U0Dzznnnndddd0100NQM1mmmm")
|
||||||
|
INST(asimd_VRSHL, "VRSHL", "1111001U0Dzznnnndddd0101NQM0mmmm")
|
||||||
|
INST(asimd_VABD, "VABD", "1111001U0Dzznnnndddd0111NQM0mmmm")
|
||||||
|
INST(asimd_VABA, "VABA", "1111001U0Dzznnnndddd0111NQM1mmmm")
|
||||||
|
INST(asimd_VMLA, "VMLA/VMLS", "1111001o0Dzznnnndddd1001NQM0mmmm")
|
||||||
|
INST(asimd_VMUL, "VMUL", "1111001P0Dzznnnndddd1001NQM1mmmm")
|
||||||
|
INST(asimd_VADDL, "VADDL/VADDW", "1111001U1Dzznnnndddd000oN0M0mmmm")
|
||||||
|
INST(asimd_VSUBL, "VSUBL/VSUBW", "1111001U1Dzznnnndddd001oN0M0mmmm")
|
||||||
|
INST(asimd_VMLAL, "VMLAL/VMLSL", "1111001U1Dzznnnndddd10o0N0M0mmmm")
|
||||||
|
INST(asimd_VMULL, "VMULL", "1111001U1Dzznnnndddd11P0N0M0mmmm")
|
||||||
|
INST(asimd_SHR, "SHR", "1111001U1Diiiiiidddd0000LQM1mmmm")
|
||||||
|
INST(asimd_SRA, "SRA", "1111001U1Diiiiiidddd0001LQM1mmmm")
|
||||||
|
INST(asimd_VRSHR, "VRSHR", "1111001U1Diiiiiidddd0010LQM1mmmm")
|
||||||
|
INST(asimd_VRSRA, "VRSRA", "1111001U1Diiiiiidddd0011LQM1mmmm")
|
||||||
|
INST(asimd_VCVT_fixed, "VCVT (fixed-point)", "1111001U1Diiiiiidddd111o0QM1mmmm")
|
||||||
|
INST(arm_UDF, "UNALLOCATED", "111101001-00--------11----------")
|
||||||
|
INST(v8_VLD_all_lanes, "VLD{1-4} (all lanes)", "111101001D10nnnndddd11nnzzTammmm")
|
||||||
|
INST(asimd_VMAX, "VMAX/VMIN (integer)", "1111001U0Dzznnnnmmmm0110NQMommmm")
|
||||||
|
INST(asimd_VPMAX_int, "VPMAX/VPMIN (integer)", "1111001U0Dzznnnndddd1010NQMommmm")
|
||||||
|
INST(asimd_VQSHL, "VQSHL", "1111001U1Diiiiiidddd011oLQM1mmmm")
|
||||||
|
INST(arm_UDF, "UNALLOCATED", "111101000--0--------11----------")
|
||||||
|
INST(v8_VST_multiple, "VST{1-4} (multiple)", "111101000D00nnnnddddxxxxzzaammmm")
|
||||||
|
INST(v8_VLD_multiple, "VLD{1-4} (multiple)", "111101000D10nnnnddddxxxxzzaammmm")
|
||||||
|
INST(v8_VST_single, "VST{1-4} (single)", "111101001D00nnnnddddzzNNaaaammmm")
|
||||||
|
INST(v8_VLD_single, "VLD{1-4} (single)", "111101001D10nnnnddddzzNNaaaammmm")
|
||||||
|
INST(asimd_VMLA_scalar, "VMLA (scalar)", "1111001Q1Dzznnnndddd0o0FN1M0mmmm")
|
||||||
|
INST(asimd_VMLAL_scalar, "VMLAL (scalar)", "1111001U1dzznnnndddd0o10N1M0mmmm")
|
||||||
|
INST(asimd_VMUL_scalar, "VMUL (scalar)", "1111001Q1Dzznnnndddd100FN1M0mmmm")
|
||||||
|
INST(asimd_VMULL_scalar, "VMULL (scalar)", "1111001U1Dzznnnndddd1010N1M0mmmm")
|
||||||
|
INST(asimd_VQDMULL_scalar, "VQDMULL (scalar)", "111100101Dzznnnndddd1011N1M0mmmm")
|
||||||
|
INST(asimd_VQDMULH_scalar, "VQDMULH (scalar)", "1111001Q1Dzznnnndddd1100N1M0mmmm")
|
||||||
|
INST(asimd_VQRDMULH_scalar, "VQRDMULH (scalar)", "1111001Q1Dzznnnndddd1101N1M0mmmm")
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
|
|
@ -24,8 +24,8 @@ template<typename Visitor>
|
||||||
using Thumb16Matcher = Decoder::Matcher<Visitor, u16>;
|
using Thumb16Matcher = Decoder::Matcher<Visitor, u16>;
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::reference_wrapper<const Thumb16Matcher<V>>> DecodeThumb16(u16 instruction) {
|
static std::optional<std::reference_wrapper<const Thumb16Matcher<V>>> DecodeThumb16(u16 instruction) {
|
||||||
alignas(64) static const std::vector<Thumb16Matcher<V>> table = {
|
alignas(64) static const auto table = std::array{
|
||||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Thumb16Matcher, fn, name, Decoder::detail::StringToArray<16>(bitstring)),
|
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Thumb16Matcher, fn, name, Decoder::detail::StringToArray<16>(bitstring)),
|
||||||
#include "./thumb16.inc"
|
#include "./thumb16.inc"
|
||||||
#undef INST
|
#undef INST
|
||||||
|
|
@ -37,7 +37,7 @@ std::optional<std::reference_wrapper<const Thumb16Matcher<V>>> DecodeThumb16(u16
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::string_view> GetNameThumb16(u32 inst) noexcept {
|
static std::optional<std::string_view> GetNameThumb16(u32 inst) noexcept {
|
||||||
std::vector<std::pair<std::string_view, Thumb16Matcher<V>>> list = {
|
std::vector<std::pair<std::string_view, Thumb16Matcher<V>>> list = {
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(Thumb16Matcher, fn, name, Decoder::detail::StringToArray<16>(bitstring)) },
|
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(Thumb16Matcher, fn, name, Decoder::detail::StringToArray<16>(bitstring)) },
|
||||||
#include "./thumb16.inc"
|
#include "./thumb16.inc"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
|
|
@ -23,8 +23,8 @@ template<typename Visitor>
|
||||||
using Thumb32Matcher = Decoder::Matcher<Visitor, u32>;
|
using Thumb32Matcher = Decoder::Matcher<Visitor, u32>;
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::reference_wrapper<const Thumb32Matcher<V>>> DecodeThumb32(u32 instruction) {
|
static std::optional<std::reference_wrapper<const Thumb32Matcher<V>>> DecodeThumb32(u32 instruction) {
|
||||||
alignas(64) static const std::vector<Thumb32Matcher<V>> table = {
|
alignas(64) static const auto table = std::array{
|
||||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Thumb32Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Thumb32Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||||
#include "./thumb32.inc"
|
#include "./thumb32.inc"
|
||||||
#undef INST
|
#undef INST
|
||||||
|
|
@ -36,7 +36,7 @@ std::optional<std::reference_wrapper<const Thumb32Matcher<V>>> DecodeThumb32(u32
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::string_view> GetNameThumb32(u32 inst) noexcept {
|
static std::optional<std::string_view> GetNameThumb32(u32 inst) noexcept {
|
||||||
std::vector<std::pair<std::string_view, Thumb32Matcher<V>>> list = {
|
std::vector<std::pair<std::string_view, Thumb32Matcher<V>>> list = {
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(Thumb32Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(Thumb32Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
||||||
#include "./thumb32.inc"
|
#include "./thumb32.inc"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
|
|
@ -24,7 +24,7 @@ template<typename Visitor>
|
||||||
using VFPMatcher = Decoder::Matcher<Visitor, u32>;
|
using VFPMatcher = Decoder::Matcher<Visitor, u32>;
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::reference_wrapper<const VFPMatcher<V>>> DecodeVFP(u32 instruction) {
|
static std::optional<std::reference_wrapper<const VFPMatcher<V>>> DecodeVFP(u32 instruction) {
|
||||||
using Table = std::vector<VFPMatcher<V>>;
|
using Table = std::vector<VFPMatcher<V>>;
|
||||||
alignas(64) static const struct Tables {
|
alignas(64) static const struct Tables {
|
||||||
Table unconditional;
|
Table unconditional;
|
||||||
|
|
@ -52,7 +52,7 @@ std::optional<std::reference_wrapper<const VFPMatcher<V>>> DecodeVFP(u32 instruc
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::string_view> GetNameVFP(u32 inst) noexcept {
|
static std::optional<std::string_view> GetNameVFP(u32 inst) noexcept {
|
||||||
std::vector<std::pair<std::string_view, VFPMatcher<V>>> list = {
|
std::vector<std::pair<std::string_view, VFPMatcher<V>>> list = {
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(VFPMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(VFPMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
||||||
#include "./vfp.inc"
|
#include "./vfp.inc"
|
||||||
|
|
|
||||||
|
|
@ -36,33 +36,19 @@ inline size_t ToFastLookupIndex(u32 instruction) {
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
constexpr DecodeTable<V> GetDecodeTable() {
|
inline DecodeTable<V> GetDecodeTable() {
|
||||||
std::vector<std::pair<const char*, Matcher<V>>> list = {
|
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
|
||||||
#include "./a64.inc"
|
|
||||||
#undef INST
|
|
||||||
};
|
|
||||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
|
||||||
std::stable_sort(list.begin(), list.end(), [](const auto& a, const auto& b) {
|
|
||||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
|
||||||
return mcl::bit::count_ones(a.second.GetMask()) > mcl::bit::count_ones(b.second.GetMask());
|
|
||||||
});
|
|
||||||
// Exceptions to the above rule of thumb.
|
|
||||||
std::stable_partition(list.begin(), list.end(), [&](const auto& e) {
|
|
||||||
return std::set<std::string>{
|
|
||||||
"MOVI, MVNI, ORR, BIC (vector, immediate)",
|
|
||||||
"FMOV (vector, immediate)",
|
|
||||||
"Unallocated SIMD modified immediate",
|
|
||||||
}.count(e.first) > 0;
|
|
||||||
});
|
|
||||||
DecodeTable<V> table{};
|
DecodeTable<V> table{};
|
||||||
for (size_t i = 0; i < table.size(); ++i) {
|
for (size_t i = 0; i < table.size(); ++i) {
|
||||||
for (auto const& e : list) {
|
// PLEASE HEAP ELLIDE
|
||||||
const auto expect = detail::ToFastLookupIndex(e.second.GetExpected());
|
for (auto const& e : std::vector<Matcher<V>>{
|
||||||
const auto mask = detail::ToFastLookupIndex(e.second.GetMask());
|
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||||
if ((i & mask) == expect) {
|
#include "./a64.inc"
|
||||||
table[i].push_back(e.second);
|
#undef INST
|
||||||
}
|
}) {
|
||||||
|
const auto expect = detail::ToFastLookupIndex(e.GetExpected());
|
||||||
|
const auto mask = detail::ToFastLookupIndex(e.GetMask());
|
||||||
|
if ((i & mask) == expect)
|
||||||
|
table[i].push_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return table;
|
return table;
|
||||||
|
|
@ -70,7 +56,7 @@ constexpr DecodeTable<V> GetDecodeTable() {
|
||||||
|
|
||||||
/// In practice it must always suceed, otherwise something else unrelated would have gone awry
|
/// In practice it must always suceed, otherwise something else unrelated would have gone awry
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::reference_wrapper<const Matcher<V>>> Decode(u32 instruction) {
|
inline std::optional<std::reference_wrapper<const Matcher<V>>> Decode(u32 instruction) {
|
||||||
alignas(64) static const auto table = GetDecodeTable<V>();
|
alignas(64) static const auto table = GetDecodeTable<V>();
|
||||||
const auto& subtable = table[detail::ToFastLookupIndex(instruction)];
|
const auto& subtable = table[detail::ToFastLookupIndex(instruction)];
|
||||||
auto iter = std::find_if(subtable.begin(), subtable.end(), [instruction](const auto& matcher) {
|
auto iter = std::find_if(subtable.begin(), subtable.end(), [instruction](const auto& matcher) {
|
||||||
|
|
@ -82,7 +68,7 @@ std::optional<std::reference_wrapper<const Matcher<V>>> Decode(u32 instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
std::optional<std::string_view> GetName(u32 inst) noexcept {
|
inline std::optional<std::string_view> GetName(u32 inst) noexcept {
|
||||||
std::vector<std::pair<std::string_view, Matcher<V>>> list = {
|
std::vector<std::pair<std::string_view, Matcher<V>>> list = {
|
||||||
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
#define INST(fn, name, bitstring) { name, DYNARMIC_DECODER_GET_MATCHER(Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)) },
|
||||||
#include "./a64.inc"
|
#include "./a64.inc"
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -109,12 +109,12 @@ public:
|
||||||
return static_cast<u32>(other_cpu_addr - cpu_addr);
|
return static_cast<u32>(other_cpu_addr - cpu_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getLRUID() const noexcept {
|
u64 GetFrameTick() const noexcept {
|
||||||
return lru_id;
|
return frame_tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLRUID(size_t lru_id_) {
|
void SetFrameTick(u64 tick) noexcept {
|
||||||
lru_id = lru_id_;
|
frame_tick = tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SizeBytes() const {
|
size_t SizeBytes() const {
|
||||||
|
|
@ -125,7 +125,7 @@ private:
|
||||||
VAddr cpu_addr = 0;
|
VAddr cpu_addr = 0;
|
||||||
BufferFlagBits flags{};
|
BufferFlagBits flags{};
|
||||||
int stream_score = 0;
|
int stream_score = 0;
|
||||||
size_t lru_id = SIZE_MAX;
|
u64 frame_tick = 0;
|
||||||
size_t size_bytes = 0;
|
size_t size_bytes = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,17 +58,22 @@ void BufferCache<P>::RunGarbageCollector() {
|
||||||
const bool aggressive_gc = total_used_memory >= critical_memory;
|
const bool aggressive_gc = total_used_memory >= critical_memory;
|
||||||
const u64 ticks_to_destroy = aggressive_gc ? 60 : 120;
|
const u64 ticks_to_destroy = aggressive_gc ? 60 : 120;
|
||||||
int num_iterations = aggressive_gc ? 64 : 32;
|
int num_iterations = aggressive_gc ? 64 : 32;
|
||||||
const auto clean_up = [this, &num_iterations](BufferId buffer_id) {
|
const u64 threshold = frame_tick - ticks_to_destroy;
|
||||||
|
boost::container::small_vector<BufferId, 64> expired;
|
||||||
|
for (auto [id, buffer] : slot_buffers) {
|
||||||
|
if (buffer->GetFrameTick() < threshold) {
|
||||||
|
expired.push_back(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto buffer_id : expired) {
|
||||||
if (num_iterations == 0) {
|
if (num_iterations == 0) {
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
--num_iterations;
|
--num_iterations;
|
||||||
auto& buffer = slot_buffers[buffer_id];
|
auto& buffer = slot_buffers[buffer_id];
|
||||||
DownloadBufferMemory(buffer);
|
DownloadBufferMemory(buffer);
|
||||||
DeleteBuffer(buffer_id);
|
DeleteBuffer(buffer_id);
|
||||||
return false;
|
}
|
||||||
};
|
|
||||||
lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, clean_up);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
|
@ -1595,10 +1600,9 @@ void BufferCache<P>::ChangeRegister(BufferId buffer_id) {
|
||||||
const auto size = buffer.SizeBytes();
|
const auto size = buffer.SizeBytes();
|
||||||
if (insert) {
|
if (insert) {
|
||||||
total_used_memory += Common::AlignUp(size, 1024);
|
total_used_memory += Common::AlignUp(size, 1024);
|
||||||
buffer.setLRUID(lru_cache.Insert(buffer_id, frame_tick));
|
buffer.SetFrameTick(frame_tick);
|
||||||
} else {
|
} else {
|
||||||
total_used_memory -= Common::AlignUp(size, 1024);
|
total_used_memory -= Common::AlignUp(size, 1024);
|
||||||
lru_cache.Free(buffer.getLRUID());
|
|
||||||
}
|
}
|
||||||
const DAddr device_addr_begin = buffer.CpuAddr();
|
const DAddr device_addr_begin = buffer.CpuAddr();
|
||||||
const DAddr device_addr_end = device_addr_begin + size;
|
const DAddr device_addr_end = device_addr_begin + size;
|
||||||
|
|
@ -1616,7 +1620,7 @@ void BufferCache<P>::ChangeRegister(BufferId buffer_id) {
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
|
void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
|
||||||
if (buffer_id != NULL_BUFFER_ID) {
|
if (buffer_id != NULL_BUFFER_ID) {
|
||||||
lru_cache.Touch(buffer.getLRUID(), frame_tick);
|
buffer.SetFrameTick(frame_tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/div_ceil.h"
|
#include "common/div_ceil.h"
|
||||||
#include "common/literals.h"
|
#include "common/literals.h"
|
||||||
#include "common/lru_cache.h"
|
|
||||||
#include "common/range_sets.h"
|
#include "common/range_sets.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
|
@ -506,11 +505,6 @@ private:
|
||||||
size_t immediate_buffer_capacity = 0;
|
size_t immediate_buffer_capacity = 0;
|
||||||
Common::ScratchBuffer<u8> immediate_buffer_alloc;
|
Common::ScratchBuffer<u8> immediate_buffer_alloc;
|
||||||
|
|
||||||
struct LRUItemParams {
|
|
||||||
using ObjectType = BufferId;
|
|
||||||
using TickType = u64;
|
|
||||||
};
|
|
||||||
Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
|
|
||||||
u64 frame_tick = 0;
|
u64 frame_tick = 0;
|
||||||
u64 total_used_memory = 0;
|
u64 total_used_memory = 0;
|
||||||
u64 minimum_memory = 0;
|
u64 minimum_memory = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
|
|
@ -122,7 +122,35 @@ void DmaPusher::ProcessCommands(std::span<const CommandHeader> commands) {
|
||||||
dma_state.is_last_call = true;
|
dma_state.is_last_call = true;
|
||||||
index += max_write;
|
index += max_write;
|
||||||
} else if (dma_state.method_count) {
|
} else if (dma_state.method_count) {
|
||||||
auto const command_header = commands[index]; //can copy
|
if (!dma_state.non_incrementing && !dma_increment_once &&
|
||||||
|
dma_state.method >= non_puller_methods) {
|
||||||
|
auto subchannel = subchannels[dma_state.subchannel];
|
||||||
|
const u32 available = u32(std::min<size_t>(
|
||||||
|
index + dma_state.method_count, commands.size()) - index);
|
||||||
|
u32 batch = 0;
|
||||||
|
u32 method = dma_state.method;
|
||||||
|
while (batch < available) {
|
||||||
|
const bool needs_exec =
|
||||||
|
(method < Engines::EngineInterface::EXECUTION_MASK_TABLE_SIZE)
|
||||||
|
? subchannel->execution_mask[method]
|
||||||
|
: subchannel->execution_mask_default;
|
||||||
|
if (needs_exec) break;
|
||||||
|
batch++;
|
||||||
|
method++;
|
||||||
|
}
|
||||||
|
if (batch > 0) {
|
||||||
|
auto& sink = subchannel->method_sink;
|
||||||
|
sink.reserve(sink.size() + batch);
|
||||||
|
for (u32 j = 0; j < batch; j++) {
|
||||||
|
sink.emplace_back(dma_state.method + j, commands[index + j].argument);
|
||||||
|
}
|
||||||
|
dma_state.method += batch;
|
||||||
|
dma_state.method_count -= batch;
|
||||||
|
index += batch;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto const command_header = commands[index];
|
||||||
dma_state.dma_word_offset = u32(index * sizeof(u32));
|
dma_state.dma_word_offset = u32(index * sizeof(u32));
|
||||||
dma_state.is_last_call = dma_state.method_count <= 1;
|
dma_state.is_last_call = dma_state.method_count <= 1;
|
||||||
CallMethod(command_header.argument);
|
CallMethod(command_header.argument);
|
||||||
|
|
@ -181,7 +209,11 @@ void DmaPusher::CallMethod(u32 argument) const {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
auto subchannel = subchannels[dma_state.subchannel];
|
auto subchannel = subchannels[dma_state.subchannel];
|
||||||
if (!subchannel->execution_mask[dma_state.method]) {
|
const bool needs_execution =
|
||||||
|
(dma_state.method < Engines::EngineInterface::EXECUTION_MASK_TABLE_SIZE)
|
||||||
|
? subchannel->execution_mask[dma_state.method]
|
||||||
|
: subchannel->execution_mask_default;
|
||||||
|
if (!needs_execution) {
|
||||||
subchannel->method_sink.emplace_back(dma_state.method, argument);
|
subchannel->method_sink.emplace_back(dma_state.method, argument);
|
||||||
} else {
|
} else {
|
||||||
subchannel->ConsumeSink();
|
subchannel->ConsumeSink();
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <bitset>
|
#include <array>
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
#include <boost/container/small_vector.hpp>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
|
@ -41,8 +41,11 @@ public:
|
||||||
ConsumeSinkImpl();
|
ConsumeSinkImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::bitset<(std::numeric_limits<u16>::max)()> execution_mask{};
|
static constexpr size_t EXECUTION_MASK_TABLE_SIZE = 0xE00;
|
||||||
std::vector<std::pair<u32, u32>> method_sink{};
|
|
||||||
|
std::array<u8, EXECUTION_MASK_TABLE_SIZE> execution_mask{};
|
||||||
|
bool execution_mask_default{};
|
||||||
|
boost::container::small_vector<std::pair<u32, u32>, 64> method_sink{};
|
||||||
bool current_dirty{};
|
bool current_dirty{};
|
||||||
GPUVAddr current_dma_segment;
|
GPUVAddr current_dma_segment;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Fermi2D::Fermi2D(MemoryManager& memory_manager_) : memory_manager{memory_manager
|
||||||
regs.src.depth = 1;
|
regs.src.depth = 1;
|
||||||
regs.dst.depth = 1;
|
regs.dst.depth = 1;
|
||||||
|
|
||||||
execution_mask.reset();
|
execution_mask.fill(0);
|
||||||
execution_mask[FERMI2D_REG_INDEX(pixels_from_memory.src_y0) + 1] = true;
|
execution_mask[FERMI2D_REG_INDEX(pixels_from_memory.src_y0) + 1] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Tegra::Engines {
|
||||||
|
|
||||||
KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
|
KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
|
||||||
: system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {
|
: system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {
|
||||||
execution_mask.reset();
|
execution_mask.fill(0);
|
||||||
execution_mask[KEPLER_COMPUTE_REG_INDEX(exec_upload)] = true;
|
execution_mask[KEPLER_COMPUTE_REG_INDEX(exec_upload)] = true;
|
||||||
execution_mask[KEPLER_COMPUTE_REG_INDEX(data_upload)] = true;
|
execution_mask[KEPLER_COMPUTE_REG_INDEX(data_upload)] = true;
|
||||||
execution_mask[KEPLER_COMPUTE_REG_INDEX(launch)] = true;
|
execution_mask[KEPLER_COMPUTE_REG_INDEX(launch)] = true;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ KeplerMemory::~KeplerMemory() = default;
|
||||||
void KeplerMemory::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
|
void KeplerMemory::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
|
||||||
upload_state.BindRasterizer(rasterizer_);
|
upload_state.BindRasterizer(rasterizer_);
|
||||||
|
|
||||||
execution_mask.reset();
|
execution_mask.fill(0);
|
||||||
execution_mask[KEPLERMEMORY_REG_INDEX(exec)] = true;
|
execution_mask[KEPLERMEMORY_REG_INDEX(exec)] = true;
|
||||||
execution_mask[KEPLERMEMORY_REG_INDEX(data)] = true;
|
execution_mask[KEPLERMEMORY_REG_INDEX(data)] = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
|
@ -37,9 +39,10 @@ Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
|
||||||
{
|
{
|
||||||
dirty.flags.flip();
|
dirty.flags.flip();
|
||||||
InitializeRegisterDefaults();
|
InitializeRegisterDefaults();
|
||||||
execution_mask.reset();
|
execution_mask.fill(0);
|
||||||
for (size_t i = 0; i < execution_mask.size(); i++)
|
for (size_t i = 0; i < EXECUTION_MASK_TABLE_SIZE; i++)
|
||||||
execution_mask[i] = IsMethodExecutable(u32(i));
|
execution_mask[i] = IsMethodExecutable(u32(i));
|
||||||
|
execution_mask_default = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxwell3D::~Maxwell3D() = default;
|
Maxwell3D::~Maxwell3D() = default;
|
||||||
|
|
@ -298,18 +301,27 @@ u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ConsumeSinkImpl() {
|
void Maxwell3D::ConsumeSinkImpl() {
|
||||||
|
std::stable_sort(method_sink.begin(), method_sink.end(),
|
||||||
|
[](const auto& a, const auto& b) { return a.first < b.first; });
|
||||||
|
|
||||||
|
const auto sink_size = method_sink.size();
|
||||||
const auto control = shadow_state.shadow_ram_control;
|
const auto control = shadow_state.shadow_ram_control;
|
||||||
if (control == Regs::ShadowRamControl::Track || control == Regs::ShadowRamControl::TrackWithFilter) {
|
if (control == Regs::ShadowRamControl::Track || control == Regs::ShadowRamControl::TrackWithFilter) {
|
||||||
for (auto [method, value] : method_sink) {
|
for (size_t i = 0; i < sink_size; ++i) {
|
||||||
|
const auto [method, value] = method_sink[i];
|
||||||
shadow_state.reg_array[method] = value;
|
shadow_state.reg_array[method] = value;
|
||||||
ProcessDirtyRegisters(method, value);
|
ProcessDirtyRegisters(method, value);
|
||||||
}
|
}
|
||||||
} else if (control == Regs::ShadowRamControl::Replay) {
|
} else if (control == Regs::ShadowRamControl::Replay) {
|
||||||
for (auto [method, value] : method_sink)
|
for (size_t i = 0; i < sink_size; ++i) {
|
||||||
|
const auto [method, value] = method_sink[i];
|
||||||
ProcessDirtyRegisters(method, shadow_state.reg_array[method]);
|
ProcessDirtyRegisters(method, shadow_state.reg_array[method]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto [method, value] : method_sink)
|
for (size_t i = 0; i < sink_size; ++i) {
|
||||||
|
const auto [method, value] = method_sink[i];
|
||||||
ProcessDirtyRegisters(method, value);
|
ProcessDirtyRegisters(method, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
method_sink.clear();
|
method_sink.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ using namespace Texture;
|
||||||
|
|
||||||
MaxwellDMA::MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_)
|
MaxwellDMA::MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_)
|
||||||
: system{system_}, memory_manager{memory_manager_} {
|
: system{system_}, memory_manager{memory_manager_} {
|
||||||
execution_mask.reset();
|
execution_mask.fill(0);
|
||||||
execution_mask[offsetof(Regs, launch_dma) / sizeof(u32)] = true;
|
execution_mask[offsetof(Regs, launch_dma) / sizeof(u32)] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,8 +118,6 @@ if (NOT GLSLANG_ERROR STREQUAL "")
|
||||||
set(QUIET_FLAG "")
|
set(QUIET_FLAG "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Shader files must depend on their directory otherwise *BSD make will spontaneously combust
|
|
||||||
file(MAKE_DIRECTORY "${SHADER_DIR}")
|
|
||||||
foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES})
|
foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES})
|
||||||
get_filename_component(FILENAME ${SOURCE_FILE} NAME)
|
get_filename_component(FILENAME ${SOURCE_FILE} NAME)
|
||||||
string(REPLACE "." "_" SHADER_NAME ${FILENAME})
|
string(REPLACE "." "_" SHADER_NAME ${FILENAME})
|
||||||
|
|
@ -135,7 +133,6 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES})
|
||||||
${SOURCE_FILE}
|
${SOURCE_FILE}
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${INPUT_FILE}
|
${INPUT_FILE}
|
||||||
${SHADER_DIR}
|
|
||||||
# HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified
|
# HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified
|
||||||
)
|
)
|
||||||
set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE})
|
set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE})
|
||||||
|
|
@ -151,8 +148,6 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES})
|
||||||
${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION}
|
${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION}
|
||||||
MAIN_DEPENDENCY
|
MAIN_DEPENDENCY
|
||||||
${SOURCE_FILE}
|
${SOURCE_FILE}
|
||||||
DEPENDS
|
|
||||||
${SHADER_DIR}
|
|
||||||
)
|
)
|
||||||
set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE})
|
set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE})
|
||||||
endif()
|
endif()
|
||||||
|
|
@ -172,7 +167,6 @@ foreach(FILEPATH IN ITEMS ${FIDELITYFX_FILES})
|
||||||
${SOURCE_FILE}
|
${SOURCE_FILE}
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${INPUT_FILE}
|
${INPUT_FILE}
|
||||||
${SHADER_DIR}
|
|
||||||
# HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified
|
# HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified
|
||||||
)
|
)
|
||||||
set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE})
|
set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE})
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -102,7 +105,7 @@ struct ImageBase {
|
||||||
VAddr cpu_addr_end = 0;
|
VAddr cpu_addr_end = 0;
|
||||||
|
|
||||||
u64 modification_tick = 0;
|
u64 modification_tick = 0;
|
||||||
size_t lru_index = SIZE_MAX;
|
u64 last_use_tick = 0;
|
||||||
|
|
||||||
std::array<u32, MAX_MIP_LEVELS> mip_level_offsets{};
|
std::array<u32, MAX_MIP_LEVELS> mip_level_offsets{};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
@ -118,24 +119,17 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::RunGarbageCollector() {
|
void TextureCache<P>::RunGarbageCollector() {
|
||||||
bool high_priority_mode = false;
|
bool high_priority_mode = total_used_memory >= expected_memory;
|
||||||
bool aggressive_mode = false;
|
bool aggressive_mode = false;
|
||||||
u64 ticks_to_destroy = 0;
|
u64 ticks_to_destroy = high_priority_mode ? 25ULL : 50ULL;
|
||||||
size_t num_iterations = 0;
|
size_t num_iterations = high_priority_mode ? 20 : 10;
|
||||||
|
|
||||||
const auto Configure = [&](bool allow_aggressive) {
|
|
||||||
high_priority_mode = total_used_memory >= expected_memory;
|
|
||||||
aggressive_mode = allow_aggressive && total_used_memory >= critical_memory;
|
|
||||||
ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL;
|
|
||||||
num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10);
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto Cleanup = [this, &num_iterations, &high_priority_mode,
|
const auto Cleanup = [this, &num_iterations, &high_priority_mode,
|
||||||
&aggressive_mode](ImageId image_id) {
|
&aggressive_mode](ImageId image_id) {
|
||||||
if (num_iterations == 0) {
|
if (num_iterations == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
--num_iterations;
|
|
||||||
auto& image = slot_images[image_id];
|
auto& image = slot_images[image_id];
|
||||||
|
|
||||||
// Never delete recently allocated sparse textures (within 3 frames)
|
// Never delete recently allocated sparse textures (within 3 frames)
|
||||||
|
|
@ -145,12 +139,9 @@ void TextureCache<P>::RunGarbageCollector() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (True(image.flags & ImageFlagBits::IsDecoding)) {
|
if (True(image.flags & ImageFlagBits::IsDecoding)) {
|
||||||
// This image is still being decoded, deleting it will invalidate the slot
|
|
||||||
// used by the async decoder thread.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prioritize large sparse textures for cleanup
|
|
||||||
const bool is_large_sparse = lowmemorydevice &&
|
const bool is_large_sparse = lowmemorydevice &&
|
||||||
image.info.is_sparse &&
|
image.info.is_sparse &&
|
||||||
image.guest_size_bytes >= 256_MiB;
|
image.guest_size_bytes >= 256_MiB;
|
||||||
|
|
@ -166,6 +157,8 @@ void TextureCache<P>::RunGarbageCollector() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--num_iterations;
|
||||||
|
|
||||||
if (must_download && !is_large_sparse) {
|
if (must_download && !is_large_sparse) {
|
||||||
auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes);
|
auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes);
|
||||||
const auto copies = FixSmallVectorADL(FullDownloadCopies(image.info));
|
const auto copies = FixSmallVectorADL(FullDownloadCopies(image.info));
|
||||||
|
|
@ -183,7 +176,6 @@ void TextureCache<P>::RunGarbageCollector() {
|
||||||
|
|
||||||
if (total_used_memory < critical_memory) {
|
if (total_used_memory < critical_memory) {
|
||||||
if (aggressive_mode) {
|
if (aggressive_mode) {
|
||||||
// Sink the aggresiveness.
|
|
||||||
num_iterations >>= 2;
|
num_iterations >>= 2;
|
||||||
aggressive_mode = false;
|
aggressive_mode = false;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -196,31 +188,64 @@ void TextureCache<P>::RunGarbageCollector() {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Aggressively clear massive sparse textures
|
const auto SortByAge = [this](auto& vec) {
|
||||||
if (total_used_memory >= expected_memory) {
|
std::sort(vec.begin(), vec.end(), [this](ImageId a, ImageId b) {
|
||||||
lru_cache.ForEachItemBelow(frame_tick, [&](ImageId image_id) {
|
return slot_images[a].last_use_tick < slot_images[b].last_use_tick;
|
||||||
auto& image = slot_images[image_id];
|
|
||||||
// Only target sparse textures that are old enough
|
|
||||||
if (lowmemorydevice &&
|
|
||||||
image.info.is_sparse &&
|
|
||||||
image.guest_size_bytes >= 256_MiB &&
|
|
||||||
image.allocation_tick < frame_tick - 3) {
|
|
||||||
LOG_DEBUG(HW_GPU, "GC targeting old sparse texture at 0x{:X} ({} MiB, age: {} frames)",
|
|
||||||
image.gpu_addr, image.guest_size_bytes / (1024 * 1024),
|
|
||||||
frame_tick - image.allocation_tick);
|
|
||||||
return Cleanup(image_id);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Single pass: collect all candidates, classified by tier
|
||||||
|
const u64 normal_threshold = frame_tick > ticks_to_destroy ? frame_tick - ticks_to_destroy : 0;
|
||||||
|
const u64 aggressive_threshold = frame_tick > 10 ? frame_tick - 10 : 0;
|
||||||
|
boost::container::small_vector<ImageId, 64> sparse_candidates;
|
||||||
|
boost::container::small_vector<ImageId, 64> expired;
|
||||||
|
boost::container::small_vector<ImageId, 64> aggressive_expired;
|
||||||
|
|
||||||
|
for (auto [id, image] : slot_images) {
|
||||||
|
if (False(image->flags & ImageFlagBits::Registered)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const u64 tick = image->last_use_tick;
|
||||||
|
if (tick < normal_threshold) {
|
||||||
|
expired.push_back(id);
|
||||||
|
} else if (tick < aggressive_threshold) {
|
||||||
|
aggressive_expired.push_back(id);
|
||||||
|
} else if (high_priority_mode && tick < frame_tick &&
|
||||||
|
lowmemorydevice && image->info.is_sparse &&
|
||||||
|
image->guest_size_bytes >= 256_MiB) {
|
||||||
|
sparse_candidates.push_back(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Configure(false);
|
SortByAge(expired);
|
||||||
lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup);
|
SortByAge(aggressive_expired);
|
||||||
|
|
||||||
// If pressure is still too high, prune aggressively.
|
// Tier 1: large sparse textures under memory pressure
|
||||||
|
for (const auto image_id : sparse_candidates) {
|
||||||
|
auto& image = slot_images[image_id];
|
||||||
|
if (image.allocation_tick < frame_tick - 3) {
|
||||||
|
if (Cleanup(image_id)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 2: normal expiration
|
||||||
|
for (const auto image_id : expired) {
|
||||||
|
if (Cleanup(image_id)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 3: if still critical, use aggressive threshold with more iterations
|
||||||
if (total_used_memory >= critical_memory) {
|
if (total_used_memory >= critical_memory) {
|
||||||
Configure(true);
|
aggressive_mode = true;
|
||||||
lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup);
|
num_iterations = 40;
|
||||||
|
for (const auto image_id : aggressive_expired) {
|
||||||
|
if (Cleanup(image_id)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2027,8 +2052,8 @@ std::pair<u32, u32> TextureCache<P>::PrepareDmaImage(ImageId dst_id, GPUVAddr ba
|
||||||
const auto& image = slot_images[dst_id];
|
const auto& image = slot_images[dst_id];
|
||||||
const auto base = image.TryFindBase(base_addr);
|
const auto base = image.TryFindBase(base_addr);
|
||||||
PrepareImage(dst_id, mark_as_modified, false);
|
PrepareImage(dst_id, mark_as_modified, false);
|
||||||
const auto& new_image = slot_images[dst_id];
|
auto& new_image = slot_images[dst_id];
|
||||||
lru_cache.Touch(new_image.lru_index, frame_tick);
|
new_image.last_use_tick = frame_tick;
|
||||||
return std::make_pair(base->level, base->layer);
|
return std::make_pair(base->level, base->layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2377,7 +2402,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
|
||||||
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
|
||||||
}
|
}
|
||||||
total_used_memory += Common::AlignUp(tentative_size, 1024);
|
total_used_memory += Common::AlignUp(tentative_size, 1024);
|
||||||
image.lru_index = lru_cache.Insert(image_id, frame_tick);
|
image.last_use_tick = frame_tick;
|
||||||
|
|
||||||
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) {
|
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) {
|
||||||
(*channel_state->gpu_page_table)[page].push_back(image_id);
|
(*channel_state->gpu_page_table)[page].push_back(image_id);
|
||||||
|
|
@ -2411,7 +2436,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
|
||||||
"Trying to unregister an already registered image");
|
"Trying to unregister an already registered image");
|
||||||
image.flags &= ~ImageFlagBits::Registered;
|
image.flags &= ~ImageFlagBits::Registered;
|
||||||
image.flags &= ~ImageFlagBits::BadOverlap;
|
image.flags &= ~ImageFlagBits::BadOverlap;
|
||||||
lru_cache.Free(image.lru_index);
|
|
||||||
const auto& clear_page_table =
|
const auto& clear_page_table =
|
||||||
[image_id](u64 page, ankerl::unordered_dense::map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>& selected_page_table) {
|
[image_id](u64 page, ankerl::unordered_dense::map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>& selected_page_table) {
|
||||||
const auto page_it = selected_page_table.find(page);
|
const auto page_it = selected_page_table.find(page);
|
||||||
|
|
@ -2733,12 +2758,14 @@ void TextureCache<P>::PrepareImage(ImageId image_id, bool is_modification, bool
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RefreshContents(image, image_id);
|
RefreshContents(image, image_id);
|
||||||
SynchronizeAliases(image_id);
|
if (!image.aliased_images.empty()) {
|
||||||
|
SynchronizeAliases(image_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (is_modification) {
|
if (is_modification) {
|
||||||
MarkModification(image);
|
MarkModification(image);
|
||||||
}
|
}
|
||||||
lru_cache.Touch(image.lru_index, frame_tick);
|
image.last_use_tick = frame_tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
#include "common/literals.h"
|
#include "common/literals.h"
|
||||||
#include "common/lru_cache.h"
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include "common/scratch_buffer.h"
|
#include "common/scratch_buffer.h"
|
||||||
#include "common/slot_vector.h"
|
#include "common/slot_vector.h"
|
||||||
|
|
@ -510,11 +510,7 @@ private:
|
||||||
std::deque<std::vector<AsyncBuffer>> async_buffers;
|
std::deque<std::vector<AsyncBuffer>> async_buffers;
|
||||||
std::deque<AsyncBuffer> async_buffers_death_ring;
|
std::deque<AsyncBuffer> async_buffers_death_ring;
|
||||||
|
|
||||||
struct LRUItemParams {
|
|
||||||
using ObjectType = ImageId;
|
|
||||||
using TickType = u64;
|
|
||||||
};
|
|
||||||
Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
|
|
||||||
|
|
||||||
#ifdef YUZU_LEGACY
|
#ifdef YUZU_LEGACY
|
||||||
static constexpr size_t TICKS_TO_DESTROY = 6;
|
static constexpr size_t TICKS_TO_DESTROY = 6;
|
||||||
|
|
|
||||||
1646
tools/gendynarm.cpp
Normal file
1646
tools/gendynarm.cpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue