mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-10 05:28:56 +02:00
[dynarmic] proper LUT implementation
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
501b884661
commit
69ac655a62
5 changed files with 29 additions and 81 deletions
|
|
@ -59,7 +59,6 @@ add_library(dynarmic STATIC
|
||||||
common/fp/util.h
|
common/fp/util.h
|
||||||
common/llvm_disassemble.cpp
|
common/llvm_disassemble.cpp
|
||||||
common/llvm_disassemble.h
|
common/llvm_disassemble.h
|
||||||
common/lut_from_list.h
|
|
||||||
common/math_util.cpp
|
common/math_util.cpp
|
||||||
common/math_util.h
|
common/math_util.h
|
||||||
common/safe_ops.h
|
common/safe_ops.h
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op.h"
|
#include "dynarmic/common/fp/op.h"
|
||||||
#include "dynarmic/common/fp/rounding_mode.h"
|
#include "dynarmic/common/fp/rounding_mode.h"
|
||||||
#include "dynarmic/common/lut_from_list.h"
|
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/microinstruction.h"
|
#include "dynarmic/ir/microinstruction.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op.h"
|
#include "dynarmic/common/fp/op.h"
|
||||||
#include "dynarmic/common/fp/rounding_mode.h"
|
#include "dynarmic/common/fp/rounding_mode.h"
|
||||||
#include "dynarmic/common/lut_from_list.h"
|
|
||||||
#include "dynarmic/interface/optimization_flags.h"
|
#include "dynarmic/interface/optimization_flags.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/microinstruction.h"
|
#include "dynarmic/ir/microinstruction.h"
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
#include "dynarmic/common/fp/op.h"
|
#include "dynarmic/common/fp/op.h"
|
||||||
#include "dynarmic/common/fp/rounding_mode.h"
|
#include "dynarmic/common/fp/rounding_mode.h"
|
||||||
#include "dynarmic/common/fp/util.h"
|
#include "dynarmic/common/fp/util.h"
|
||||||
#include "dynarmic/common/lut_from_list.h"
|
|
||||||
#include "dynarmic/interface/optimization_flags.h"
|
#include "dynarmic/interface/optimization_flags.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/microinstruction.h"
|
#include "dynarmic/ir/microinstruction.h"
|
||||||
|
|
@ -1986,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();
|
||||||
|
|
@ -2107,29 +2113,29 @@ 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]{
|
||||||
|
#define ROUNDING_MODE(CASE) \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 8 && fbits == 8) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 8>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 16 && fbits == 8) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 8>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 16 && fbits == 16) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 16>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 32 && fbits == 8) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 8>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 32 && fbits == 16) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 16>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 32 && fbits == 32) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 32>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 64 && fbits == 8) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 8>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 64 && fbits == 16) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 16>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 64 && fbits == 32) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 32>; \
|
||||||
|
else if (rounding == FP::RoundingMode::CASE && fsize == 64 && fbits == 64) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, 64>;
|
||||||
|
|
||||||
using fbits_list = mp::lift_sequence<std::make_index_sequence<fsize + 1>>;
|
if (false) { /* ... */ }
|
||||||
using rounding_list = mp::list<
|
ROUNDING_MODE(ToNearest_TieEven)
|
||||||
mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
|
ROUNDING_MODE(TowardsPlusInfinity)
|
||||||
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
ROUNDING_MODE(TowardsMinusInfinity)
|
||||||
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
ROUNDING_MODE(TowardsZero)
|
||||||
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
ROUNDING_MODE(ToNearest_TieAwayFromZero)
|
||||||
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
|
else return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::TowardsZero, 64>;
|
||||||
|
}();
|
||||||
|
|
||||||
static const auto lut = Common::GenerateLookupTableFromList([]<typename I>(I) {
|
EmitTwoOpFallback<3>(code, ctx, inst, fpt_fn);
|
||||||
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC
|
|
||||||
return std::pair{
|
|
||||||
mp::lower_to_tuple_v<I>,
|
|
||||||
Common::FptrCast([](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
|
||||||
constexpr size_t fbits = mp::get<0, I>::value;
|
|
||||||
constexpr FP::RoundingMode rounding_mode = mp::get<1, I>::value;
|
|
||||||
for (size_t i = 0; i < output.size(); ++i)
|
|
||||||
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}, mp::cartesian_product<fbits_list, rounding_list>{});
|
|
||||||
|
|
||||||
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(fbits, rounding)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitFPVectorToSignedFixed16(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitFPVectorToSignedFixed16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <map>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include <mcl/mp/metafunction/apply.hpp>
|
|
||||||
#include <mcl/mp/typelist/list.hpp>
|
|
||||||
#include <mcl/type_traits/is_instance_of_template.hpp>
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# include <mcl/mp/typelist/head.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Dynarmic::Common {
|
|
||||||
|
|
||||||
// prevents this function from printing 56,000 character warning messages
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wno-stack-usage"
|
|
||||||
#endif
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wno-stack-usage"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<typename Function, typename... Values>
|
|
||||||
inline auto GenerateLookupTableFromList(Function f, mcl::mp::list<Values...>) {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
using PairT = std::invoke_result_t<Function, mcl::mp::head<mcl::mp::list<Values...>>>;
|
|
||||||
#else
|
|
||||||
using PairT = std::common_type_t<std::invoke_result_t<Function, Values>...>;
|
|
||||||
#endif
|
|
||||||
using MapT = mcl::mp::apply<std::map, PairT>;
|
|
||||||
static_assert(mcl::is_instance_of_template_v<std::pair, PairT>);
|
|
||||||
const std::initializer_list<PairT> pair_array{f(Values{})...};
|
|
||||||
return MapT(pair_array.begin(), pair_array.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Dynarmic::Common
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue