mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-24 05:22:35 +00:00
[common] rework BitField and BitUtil, use concepts whenever possible (#4076)
test no regressions especially on Liiinux Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4076 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
@@ -85,8 +85,8 @@ public:
|
||||
|
||||
/// @brief Code emitter: Calls the function
|
||||
template<typename F>
|
||||
requires std::is_pointer_v<F> && std::is_function_v<std::remove_pointer_t<F>>
|
||||
void CallFunction(F fn) {
|
||||
static_assert(std::is_pointer_v<F> && std::is_function_v<std::remove_pointer_t<F>>, "Supplied type must be a pointer to a function");
|
||||
::Common::X64::CallFarFunction(*this, fn);
|
||||
}
|
||||
|
||||
|
||||
@@ -5076,9 +5076,8 @@ void EmitX64::EmitVectorSignedSaturatedNeg64(EmitContext& ctx, IR::Inst* inst) {
|
||||
# pragma clang diagnostic ignored "-Wunused-lambda-capture"
|
||||
#endif
|
||||
template<typename T, typename U = std::make_unsigned_t<T>>
|
||||
requires std::is_signed_v<T>
|
||||
static bool VectorSignedSaturatedShiftLeft(VectorArray<T>& dst, const VectorArray<T>& data, const VectorArray<T>& shift_values) {
|
||||
static_assert(std::is_signed_v<T>, "T must be signed.");
|
||||
|
||||
bool qc_flag = false;
|
||||
|
||||
constexpr size_t bit_size_minus_one = mcl::bitsizeof<T> - 1;
|
||||
@@ -5134,9 +5133,9 @@ void EmitX64::EmitVectorSignedSaturatedShiftLeft64(EmitContext& ctx, IR::Inst* i
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires std::is_signed_v<T>
|
||||
static bool VectorSignedSaturatedShiftLeftUnsigned(VectorArray<T>& dst, const VectorArray<T>& data, u8 shift_amount) {
|
||||
using U = std::make_unsigned_t<T>;
|
||||
static_assert(std::is_signed_v<T>, "T must be signed.");
|
||||
bool qc_flag = false;
|
||||
for (size_t i = 0; i < dst.size(); i++) {
|
||||
auto const element = data[i];
|
||||
@@ -6030,17 +6029,15 @@ void EmitX64::EmitVectorUnsignedRecipSqrtEstimate(EmitContext& ctx, IR::Inst* in
|
||||
// Simple generic case for 8, 16, and 32-bit values. 64-bit values
|
||||
// will need to be special-cased as we can't simply use a larger integral size.
|
||||
template<typename T, typename U = std::make_unsigned_t<T>>
|
||||
requires std::is_signed_v<T>
|
||||
static bool EmitVectorUnsignedSaturatedAccumulateSigned(VectorArray<U>& result, const VectorArray<T>& lhs, const VectorArray<T>& rhs) {
|
||||
static_assert(std::is_signed_v<T>, "T must be signed.");
|
||||
static_assert(mcl::bitsizeof<T> < 64, "T must be less than 64 bits in size.");
|
||||
|
||||
bool qc_flag = false;
|
||||
|
||||
for (size_t i = 0; i < result.size(); i++) {
|
||||
// We treat rhs' members as unsigned, so cast to unsigned before signed to inhibit sign-extension.
|
||||
// We use the unsigned equivalent of T, as we want zero-extension to occur, rather than a plain move.
|
||||
const s64 x = s64{lhs[i]};
|
||||
const s64 y = static_cast<s64>(static_cast<std::make_unsigned_t<U>>(rhs[i]));
|
||||
const s64 y = s64(std::make_unsigned_t<U>(rhs[i]));
|
||||
const s64 sum = x + y;
|
||||
|
||||
if (sum > (std::numeric_limits<U>::max)()) {
|
||||
@@ -6050,10 +6047,9 @@ static bool EmitVectorUnsignedSaturatedAccumulateSigned(VectorArray<U>& result,
|
||||
result[i] = (std::numeric_limits<U>::min)();
|
||||
qc_flag = true;
|
||||
} else {
|
||||
result[i] = static_cast<U>(sum);
|
||||
result[i] = U(sum);
|
||||
}
|
||||
}
|
||||
|
||||
return qc_flag;
|
||||
}
|
||||
|
||||
@@ -6134,29 +6130,23 @@ void EmitX64::EmitVectorUnsignedSaturatedNarrow64(EmitContext& ctx, IR::Inst* in
|
||||
}
|
||||
|
||||
template<typename T, typename S = std::make_signed_t<T>>
|
||||
requires std::is_unsigned_v<T>
|
||||
static bool VectorUnsignedSaturatedShiftLeft(VectorArray<T>& dst, const VectorArray<T>& data, const VectorArray<T>& shift_values) {
|
||||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned type.");
|
||||
|
||||
bool qc_flag = false;
|
||||
|
||||
constexpr size_t bit_size = mcl::bitsizeof<T>;
|
||||
constexpr S negative_bit_size = -static_cast<S>(bit_size);
|
||||
|
||||
constexpr S negative_bit_size = -S(bit_size);
|
||||
for (size_t i = 0; i < dst.size(); i++) {
|
||||
const T element = data[i];
|
||||
const S shift = std::clamp(static_cast<S>(mcl::bit::sign_extend<8>(static_cast<T>(shift_values[i] & 0xFF))),
|
||||
negative_bit_size, (std::numeric_limits<S>::max)());
|
||||
|
||||
const S shift = std::clamp(S(mcl::bit::sign_extend<8>(T(shift_values[i] & 0xFF))), negative_bit_size, (std::numeric_limits<S>::max)());
|
||||
if (element == 0 || shift <= negative_bit_size) {
|
||||
dst[i] = 0;
|
||||
} else if (shift < 0) {
|
||||
dst[i] = static_cast<T>(element >> -shift);
|
||||
} else if (shift >= static_cast<S>(bit_size)) {
|
||||
dst[i] = T(element >> -shift);
|
||||
} else if (shift >= S(bit_size)) {
|
||||
dst[i] = (std::numeric_limits<T>::max)();
|
||||
qc_flag = true;
|
||||
} else {
|
||||
const T shifted = element << shift;
|
||||
|
||||
if ((shifted >> shift) != element) {
|
||||
dst[i] = (std::numeric_limits<T>::max)();
|
||||
qc_flag = true;
|
||||
|
||||
@@ -28,18 +28,11 @@ T ArithmeticShiftRight(T value, int shift_amount);
|
||||
|
||||
template<typename T>
|
||||
T LogicalShiftLeft(T value, int shift_amount) {
|
||||
static_assert(std::is_integral_v<T>);
|
||||
|
||||
if (shift_amount >= static_cast<int>(mcl::bitsizeof<T>)) {
|
||||
if (shift_amount >= int(mcl::bitsizeof<T>))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shift_amount < 0) {
|
||||
return LogicalShiftRight(value, -shift_amount);
|
||||
}
|
||||
|
||||
auto unsigned_value = static_cast<std::make_unsigned_t<T>>(value);
|
||||
return static_cast<T>(unsigned_value << shift_amount);
|
||||
return shift_amount < 0
|
||||
? LogicalShiftRight(value, -shift_amount)
|
||||
: T(std::make_unsigned_t<T>(value) << shift_amount);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -49,18 +42,11 @@ inline u128 LogicalShiftLeft(u128 value, int shift_amount) {
|
||||
|
||||
template<typename T>
|
||||
T LogicalShiftRight(T value, int shift_amount) {
|
||||
static_assert(std::is_integral_v<T>);
|
||||
|
||||
if (shift_amount >= static_cast<int>(mcl::bitsizeof<T>)) {
|
||||
if (shift_amount >= int(mcl::bitsizeof<T>))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shift_amount < 0) {
|
||||
return LogicalShiftLeft(value, -shift_amount);
|
||||
}
|
||||
|
||||
auto unsigned_value = static_cast<std::make_unsigned_t<T>>(value);
|
||||
return static_cast<T>(unsigned_value >> shift_amount);
|
||||
return shift_amount < 0
|
||||
? LogicalShiftLeft(value, -shift_amount)
|
||||
: T(std::make_unsigned_t<T>(value) >> shift_amount);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -75,34 +61,20 @@ T LogicalShiftRightDouble(T top, T bottom, int shift_amount) {
|
||||
|
||||
template<typename T>
|
||||
T ArithmeticShiftLeft(T value, int shift_amount) {
|
||||
static_assert(std::is_integral_v<T>);
|
||||
|
||||
if (shift_amount >= static_cast<int>(mcl::bitsizeof<T>)) {
|
||||
if (shift_amount >= int(mcl::bitsizeof<T>))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shift_amount < 0) {
|
||||
return ArithmeticShiftRight(value, -shift_amount);
|
||||
}
|
||||
|
||||
auto unsigned_value = static_cast<std::make_unsigned_t<T>>(value);
|
||||
return static_cast<T>(unsigned_value << shift_amount);
|
||||
return shift_amount < 0
|
||||
? ArithmeticShiftRight(value, -shift_amount)
|
||||
: T(std::make_unsigned_t<T>(value) << shift_amount);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T ArithmeticShiftRight(T value, int shift_amount) {
|
||||
static_assert(std::is_integral_v<T>);
|
||||
|
||||
if (shift_amount >= static_cast<int>(mcl::bitsizeof<T>)) {
|
||||
return mcl::bit::most_significant_bit(value) ? ~static_cast<T>(0) : 0;
|
||||
}
|
||||
|
||||
if (shift_amount < 0) {
|
||||
return ArithmeticShiftLeft(value, -shift_amount);
|
||||
}
|
||||
|
||||
auto signed_value = static_cast<std::make_signed_t<T>>(value);
|
||||
return static_cast<T>(signed_value >> shift_amount);
|
||||
if (shift_amount >= int(mcl::bitsizeof<T>))
|
||||
return mcl::bit::most_significant_bit(value) ? ~T(0) : 0;
|
||||
return shift_amount < 0
|
||||
? ArithmeticShiftLeft(value, -shift_amount)
|
||||
: T(std::make_signed_t<T>(value) >> shift_amount);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -112,7 +84,7 @@ T ArithmeticShiftRightDouble(T top, T bottom, int shift_amount) {
|
||||
|
||||
template<typename T>
|
||||
T Negate(T value) {
|
||||
return static_cast<T>(~static_cast<std::uintmax_t>(value) + 1);
|
||||
return T(~std::uintmax_t(value) + 1);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Safe
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
@@ -47,8 +50,8 @@ public:
|
||||
/// the exclusive state for processors if their exclusive region(s)
|
||||
/// contain [address, address+size).
|
||||
template<typename T, typename Function>
|
||||
requires std::is_trivially_copyable_v<T>
|
||||
bool DoExclusiveOperation(size_t processor_id, VAddr address, Function op) {
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
if (!CheckAndClear(processor_id, address)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
@@ -17,11 +20,9 @@ inline std::mt19937 g_rand_int_generator = [] {
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
requires std::is_integral_v<T>
|
||||
&& (!std::is_same_v<T, signed char> && !std::is_same_v<T, unsigned char>)
|
||||
T RandInt(T min, T max) {
|
||||
static_assert(std::is_integral_v<T>, "T must be an integral type.");
|
||||
static_assert(!std::is_same_v<T, signed char> && !std::is_same_v<T, unsigned char>,
|
||||
"Using char with uniform_int_distribution is undefined behavior.");
|
||||
|
||||
std::uniform_int_distribution<T> rand(min, max);
|
||||
return rand(detail::g_rand_int_generator);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user