Compare commits

...

4 commits

Author SHA1 Message Date
lizzie
46f19dbf6e fx 2026-03-31 01:55:21 +00:00
lizzie
dc4db5a598 fix 2026-03-31 01:55:21 +00:00
lizzie
6a8764a51b [common] unify std::random_device
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-03-31 01:55:21 +00:00
lizzie
7a8176f63f
[dynarmic] implement missing SSE3 implementations (#3301)
Implementations for SSE3 CPUs (prescott)

Instead of fixing some of the bugs with HostCall when paired with vectors, i'll simply remove as many host calls as I can within the most used vector instructions - then just minimize their usage to memory read/writes.
Emitting the raw assembly code is faster than doing a HostCall, HostCalls are VERY expensive. So this is the desired output anyways.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3301
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-31 02:53:51 +02:00
14 changed files with 1516 additions and 1026 deletions

View file

@ -134,6 +134,8 @@ add_library(
typed_address.h
uint128.h
unique_function.h
random.cpp
random.h
uuid.cpp
uuid.h
vector_math.h

19
src/common/random.cpp Normal file
View file

@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <random>
#include "common/random.h"
static std::random_device g_random_device;
namespace Common::Random {
[[nodiscard]] u32 Random32(u32 seed) noexcept {
return g_random_device();
}
[[nodiscard]] u64 Random64(u64 seed) noexcept {
return g_random_device();
}
[[nodiscard]] std::mt19937 GetMT19937() noexcept {
return std::mt19937(g_random_device());
}
}

13
src/common/random.h Normal file
View file

@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <random>
#include "common/common_types.h"
namespace Common::Random {
[[nodiscard]] u32 Random32(u32 seed) noexcept;
[[nodiscard]] u64 Random64(u64 seed) noexcept;
[[nodiscard]] std::mt19937 GetMT19937() noexcept;
}

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -10,6 +13,7 @@
#include "common/assert.h"
#include "common/tiny_mt.h"
#include "common/uuid.h"
#include "common/random.h"
namespace Common {
@ -175,21 +179,16 @@ u128 UUID::AsU128() const {
}
UUID UUID::MakeRandom() {
std::random_device device;
return MakeRandomWithSeed(device());
return MakeRandomWithSeed(Common::Random::Random32(0));
}
UUID UUID::MakeRandomWithSeed(u32 seed) {
// Create and initialize our RNG.
TinyMT rng;
rng.Initialize(seed);
UUID uuid;
// Populate the UUID with random bytes.
rng.GenerateRandomBytes(uuid.uuid.data(), sizeof(UUID));
return uuid;
}

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -7,6 +10,7 @@
#include <span>
#include "common/common_types.h"
#include "common/random.h"
#include "common/swap.h"
#include "common/uuid.h"
#include "core/hle/service/mii/mii_types.h"
@ -65,11 +69,9 @@ public:
template <typename T>
static T GetRandomValue(T min, T max) {
std::random_device device;
std::mt19937 gen(device());
std::uniform_int_distribution<u64> distribution(static_cast<u64>(min),
static_cast<u64>(max));
return static_cast<T>(distribution(gen));
std::uniform_int_distribution<u64> distribution{u64(min), u64(max)};
auto gen = Common::Random::GetMT19937();
return T(distribution(gen));
}
template <typename T>

View file

@ -6,6 +6,7 @@
#include <cstring>
#include "common/logging.h"
#include "common/random.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/content_archive.h"
@ -229,7 +230,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
// TODO: this is bad form of ASLR, it sucks
size_t aslr_offset = ((::Settings::values.rng_seed_enabled.GetValue()
? ::Settings::values.rng_seed.GetValue()
: std::rand()) * 0x734287f27) & 0xfff000;
: Common::Random::Random64(0)) * 0x734287f27) & 0xfff000;
// Setup the process code layout
if (process.LoadFromMetadata(metadata, code_size, fastmem_base, aslr_offset, is_hbl).IsError()) {

View file

@ -6,6 +6,7 @@
#include <cstring>
#include "common/settings.h"
#include "common/random.h"
#include "core/file_sys/kernel_executable.h"
#include "core/file_sys/program_metadata.h"
#include "core/hle/kernel/code_set.h"
@ -90,7 +91,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
// TODO: this is bad form of ASLR, it sucks
size_t aslr_offset = ((::Settings::values.rng_seed_enabled.GetValue()
? ::Settings::values.rng_seed.GetValue()
: std::rand()) * 0x734287f27) & 0xfff000;
: Common::Random::Random64(0)) * 0x734287f27) & 0xfff000;
// Setup the process code layout
if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset, false).IsError()) {

View file

@ -11,6 +11,7 @@
#include "common/common_types.h"
#include "common/logging.h"
#include "common/settings.h"
#include "common/random.h"
#include "common/swap.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
@ -243,7 +244,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
// TODO: this is bad form of ASLR, it sucks
size_t aslr_offset = ((::Settings::values.rng_seed_enabled.GetValue()
? ::Settings::values.rng_seed.GetValue()
: std::rand()) * 0x734287f27) & 0xfff000;
: Common::Random::Random64(0)) * 0x734287f27) & 0xfff000;
// Setup the process code layout
if (process

File diff suppressed because it is too large Load diff

View file

@ -415,6 +415,105 @@ TEST_CASE("A64: URSHL", "[a64]") {
CHECK(jit.GetVector(9) == Vector{0x0000000000000002, 0x12db8b8280e0ba});
}
TEST_CASE("A64: SQSHLU", "[a64]") {
A64TestEnv env;
A64::UserConfig jit_user_config{};
jit_user_config.callbacks = &env;
A64::Jit jit{jit_user_config};
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
code.SQSHLU(V8.B16(), V0.B16(), 1);
code.SQSHLU(V9.H8(), V1.H8(), 2);
code.SQSHLU(V10.S4(), V2.S4(), 28);
code.SQSHLU(V11.D2(), V3.D2(), 4);
code.SQSHLU(V12.S4(), V0.S4(), 1);
code.SQSHLU(V13.S4(), V1.S4(), 3);
code.SQSHLU(V14.S4(), V2.S4(), 0);
code.SQSHLU(V15.S4(), V3.S4(), 0);
jit.SetVector(0, Vector{0xffffffff'18ba6a6a, 0x7fffffff'943b954f});
jit.SetVector(1, Vector{0x0000000b'0000000f, 0xffffffff'ffffffff});
jit.SetVector(2, Vector{0x00000001'000000ff, 0x00000010'0000007f});
jit.SetVector(3, Vector{0xffffffffffffffff, 0x96dc5c140705cd04});
env.ticks_left = env.code_mem.size();
CheckedRun([&]() { jit.Run(); });
CHECK(jit.GetVector(8) == Vector{0x3000d4d4, 0xfe0000000076009e});
CHECK(jit.GetVector(9) == Vector{0x2c0000003c, 0});
CHECK(jit.GetVector(10) == Vector{0x10000000'ffffffff, 0xffffffff'ffffffff});
CHECK(jit.GetVector(11) == Vector{0, 0});
CHECK(jit.GetVector(12) == Vector{0x3174d4d4, 0xfffffffe00000000});
CHECK(jit.GetVector(13) == Vector{0x5800000078, 0});
CHECK(jit.GetVector(14) == Vector{0x1000000ff, 0x100000007f});
CHECK(jit.GetVector(15) == Vector{0, 0x705cd04});
}
TEST_CASE("A64: SMIN", "[a64]") {
A64TestEnv env;
A64::UserConfig jit_user_config{};
jit_user_config.callbacks = &env;
A64::Jit jit{jit_user_config};
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
code.SMIN(V8.B16(), V0.B16(), V3.B16());
code.SMIN(V9.H8(), V1.H8(), V2.H8());
code.SMIN(V10.S4(), V2.S4(), V3.S4());
code.SMIN(V11.S4(), V3.S4(), V3.S4());
code.SMIN(V12.S4(), V0.S4(), V3.S4());
code.SMIN(V13.S4(), V1.S4(), V2.S4());
code.SMIN(V14.S4(), V2.S4(), V1.S4());
code.SMIN(V15.S4(), V3.S4(), V0.S4());
jit.SetPC(0);
jit.SetVector(0, Vector{0xffffffff'18ba6a6a, 0x7fffffff'943b954f});
jit.SetVector(1, Vector{0x0000000b'0000000f, 0xffffffff'ffffffff});
jit.SetVector(2, Vector{0x00000001'000000ff, 0x00000010'0000007f});
jit.SetVector(3, Vector{0xffffffff'ffffffff, 0x96dc5c14'0705cd04});
env.ticks_left = 4;
CheckedRun([&]() { jit.Run(); });
REQUIRE(jit.GetVector(8) == Vector{0xffffffffffbaffff, 0x96dcffff94059504});
REQUIRE(jit.GetVector(9) == Vector{0x10000000f, 0xffffffffffffffff});
REQUIRE(jit.GetVector(10) == Vector{0xffffffffffffffff, 0x96dc5c140000007f});
}
TEST_CASE("A64: SMINP", "[a64]") {
A64TestEnv env;
A64::UserConfig jit_user_config{};
jit_user_config.callbacks = &env;
A64::Jit jit{jit_user_config};
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
code.SMINP(V8.B16(), V0.B16(), V3.B16());
code.SMINP(V9.H8(), V1.H8(), V2.H8());
code.SMINP(V10.S4(), V2.S4(), V1.S4());
code.SMINP(V11.S4(), V3.S4(), V3.S4());
code.SMINP(V12.S4(), V0.S4(), V3.S4());
code.SMINP(V13.S4(), V1.S4(), V2.S4());
code.SMINP(V14.S4(), V2.S4(), V1.S4());
code.SMINP(V15.S4(), V3.S4(), V0.S4());
jit.SetPC(0);
jit.SetVector(0, Vector{0xffffffff'18ba6a6a, 0x7fffffff'943b954f});
jit.SetVector(1, Vector{0x0000000b'0000000f, 0xffffffff'ffffffff});
jit.SetVector(2, Vector{0x00000001'000000ff, 0x00000010'0000007f});
jit.SetVector(3, Vector{0xffffffff'ffffffff, 0x96dc5c14'0705cd04});
env.ticks_left = 4;
CheckedRun([&]() { jit.Run(); });
REQUIRE(jit.GetVector(8) == Vector{0xffff9495ffffba6a, 0x961405cdffffffff});
REQUIRE(jit.GetVector(9) == Vector{0xffffffff00000000, 0});
REQUIRE(jit.GetVector(10) == Vector{0x1000000001, 0xffffffff0000000b});
REQUIRE(jit.GetVector(11) == Vector{0x96dc5c14ffffffff, 0x96dc5c14ffffffff});
REQUIRE(jit.GetVector(12) == Vector{0x943b954fffffffff, 0x96dc5c14ffffffff});
REQUIRE(jit.GetVector(13) == Vector{0xffffffff0000000b, 0x1000000001});
REQUIRE(jit.GetVector(14) == Vector{0x1000000001, 0xffffffff0000000b});
REQUIRE(jit.GetVector(15) == Vector{0x96dc5c14ffffffff, 0x943b954fffffffff});
}
TEST_CASE("A64: XTN", "[a64]") {
A64TestEnv env;
A64::UserConfig jit_user_config{};

View file

@ -4,22 +4,21 @@
#include <random>
#include <frozen/string.h>
#include "common/settings.h"
#include "common/random.h"
#include "settings_generator.h"
namespace FrontendCommon {
void GenerateSettings() {
static std::random_device rd;
auto gen = Common::Random::GetMT19937();
// Web Token
if (Settings::values.eden_token.GetValue().empty()) {
static constexpr const size_t token_length = 48;
static constexpr const frozen::string token_set = "abcdefghijklmnopqrstuvwxyz";
static std::uniform_int_distribution<int> token_dist(0, token_set.size() - 1);
std::string result;
for (size_t i = 0; i < token_length; ++i) {
size_t idx = token_dist(rd);
size_t idx = token_dist(gen);
result += token_set[idx];
}
Settings::values.eden_token.SetValue(result);
@ -27,8 +26,6 @@ void GenerateSettings() {
// Randomly generated number because, well, we fill the rest automagically ;)
// Other serial parts are filled by Region_Index
std::random_device device;
std::mt19937 gen(device());
std::uniform_int_distribution<u32> distribution(1, (std::numeric_limits<u32>::max)());
if (Settings::values.serial_unit.GetValue() == 0)
Settings::values.serial_unit.SetValue(distribution(gen));

View file

@ -1,9 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <random>
#include "common/random.h"
#include "common/input.h"
#include "hid_core/frontend/input_converter.h"
@ -119,15 +123,14 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu
.properties = properties,
};
if (TransformToButton(callback).value) {
std::random_device device;
std::mt19937 gen(device());
std::uniform_int_distribution<s16> distribution(-5000, 5000);
status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
status.gyro.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
status.gyro.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
status.gyro.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f;
auto gen = Common::Random::GetMT19937();
status.accel.x.raw_value = f32(distribution(gen)) * 0.001f;
status.accel.y.raw_value = f32(distribution(gen)) * 0.001f;
status.accel.z.raw_value = f32(distribution(gen)) * 0.001f;
status.gyro.x.raw_value = f32(distribution(gen)) * 0.001f;
status.gyro.y.raw_value = f32(distribution(gen)) * 0.001f;
status.gyro.z.raw_value = f32(distribution(gen)) * 0.001f;
}
break;
}

View file

@ -11,6 +11,7 @@
#include "common/logging.h"
#include "common/param_package.h"
#include "common/random.h"
#include "common/settings.h"
#include "input_common/drivers/udp_client.h"
#include "input_common/helpers/udp_protocol.h"
@ -31,7 +32,7 @@ public:
explicit Socket(const std::string& host, u16 port, SocketCallback callback_)
: callback(std::move(callback_)), timer(io_context),
socket(io_context, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) {
socket(io_context, udp::endpoint(udp::v4(), 0)), client_id(Common::Random::Random32(0)) {
boost::system::error_code ec{};
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
if (ec.value() != boost::system::errc::success) {
@ -64,11 +65,6 @@ public:
}
private:
u32 GenerateRandomClientId() const {
std::random_device device;
return device();
}
void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) {
if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) {
switch (*type) {

View file

@ -23,8 +23,6 @@ namespace Network {
class Room::RoomImpl {
public:
std::mt19937 random_gen; ///< Random number generator. Used for GenerateFakeIPAddress
ENetHost* server = nullptr; ///< Network interface.
std::atomic<State> state{State::Closed}; ///< Current state of the room.
@ -51,7 +49,7 @@ public:
IPBanList ip_ban_list; ///< List of banned IP addresses
mutable std::mutex ban_list_mutex; ///< Mutex for the ban lists
RoomImpl() : random_gen(std::random_device()()) {}
RoomImpl() {}
/// Thread that receives and dispatches network packets
std::optional<std::jthread> room_thread;