diff --git a/external/ircolib/file.hpp b/external/ircolib/file.hpp index 1e9b11a..b89c4b2 100644 --- a/external/ircolib/file.hpp +++ b/external/ircolib/file.hpp @@ -1,43 +1,43 @@ #pragma once -#include +#include #include #include #include +namespace ircolib { namespace fs = std::filesystem; -namespace ircolib { -static inline std::vector ReadFileBinary(const std::string &path) { - std::ifstream file(path, std::ios::binary); - return {std::istreambuf_iterator{file}, {}}; +static inline std::vector read_file_binary(const std::string &path) { + std::ifstream file(path, std::ios::binary); + return {std::istreambuf_iterator{file}, {}}; } -static inline void WriteFileBinary(const std::vector &data, const std::string &path) { - std::ofstream file(path, std::ios::binary); - std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file}); +static inline void write_file_binary(const std::vector &data, const std::string &path) { + std::ofstream file(path, std::ios::binary); + std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file}); } -static inline void WriteFileBinary(const u8 *data, const size_t size, const std::string &path) { - FILE *out = fopen(path.c_str(), "wb"); - fwrite(data, size, 1, out); - fclose(out); +static inline void write_file_binary(const u8 *data, const u32 size, const std::string &path) { + FILE *out = fopen(path.c_str(), "wb"); + fwrite(data, size, 1, out); + fclose(out); } template -static inline void WriteFileBinary(const std::array &data, const std::string &path) { - std::ofstream file(path, std::ios::binary); - std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file}); +static inline void write_file_binary(const std::array &data, const std::string &path) { + std::ofstream file(path, std::ios::binary); + std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file}); } -static inline size_t NextPow2(size_t num) { - // Taken from "Bit Twiddling Hacks" by Sean Anderson: - // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - --num; - num |= num >> 1; - num |= num >> 2; - num |= num >> 4; - num |= num >> 8; - num |= num >> 16; - return num + 1; +static inline u32 next_pow2(u32 num) { + // Taken from "Bit Twiddling Hacks" by Sean Anderson: + // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + --num; + num |= num >> 1; + num |= num >> 2; + num |= num >> 4; + num |= num >> 8; + num |= num >> 16; + return num + 1; } -} // namespace Util +} // namespace ircolib diff --git a/external/ircolib/floats.hpp b/external/ircolib/floats.hpp index 913f1de..0027e2c 100644 --- a/external/ircolib/floats.hpp +++ b/external/ircolib/floats.hpp @@ -1,106 +1,105 @@ #pragma once -#include -#include +#include namespace ircolib { static inline auto roundCeil(float f) { #ifdef SIMD_SUPPORT - __m128 t = _mm_set_ss(f); - t = _mm_round_ss(t, t, _MM_FROUND_TO_POS_INF); - return _mm_cvtss_f32(t); + __m128 t = _mm_set_ss(f); + t = _mm_round_ss(t, t, _MM_FROUND_TO_POS_INF); + return _mm_cvtss_f32(t); #else - return ceilf(f); + return ceilf(f); #endif } static inline auto roundCeil(double f) { #ifdef SIMD_SUPPORT - __m128d t = _mm_set_sd(f); - t = _mm_round_sd(t, t, _MM_FROUND_TO_POS_INF); - return _mm_cvtsd_f64(t); + __m128d t = _mm_set_sd(f); + t = _mm_round_sd(t, t, _MM_FROUND_TO_POS_INF); + return _mm_cvtsd_f64(t); #else - return ceil(f); + return ceil(f); #endif } static inline auto roundNearest(float f) { #ifdef SIMD_SUPPORT - __m128 t = _mm_set_ss(f); - t = _mm_round_ss(t, t, _MM_FROUND_TO_NEAREST_INT); - return _mm_cvtss_f32(t); + __m128 t = _mm_set_ss(f); + t = _mm_round_ss(t, t, _MM_FROUND_TO_NEAREST_INT); + return _mm_cvtss_f32(t); #else - return roundf(f); + return roundf(f); #endif } static inline auto roundNearest(double f) { #ifdef SIMD_SUPPORT - __m128d t = _mm_set_sd(f); - t = _mm_round_sd(t, t, _MM_FROUND_TO_NEAREST_INT); - return _mm_cvtsd_f64(t); + __m128d t = _mm_set_sd(f); + t = _mm_round_sd(t, t, _MM_FROUND_TO_NEAREST_INT); + return _mm_cvtsd_f64(t); #else - return round(f); + return round(f); #endif } static inline auto roundCurrent(float f) { #ifdef SIMD_SUPPORT - auto t = _mm_set_ss(f); - t = _mm_round_ss(t, t, _MM_FROUND_CUR_DIRECTION); - return _mm_cvtss_f32(t); + auto t = _mm_set_ss(f); + t = _mm_round_ss(t, t, _MM_FROUND_CUR_DIRECTION); + return _mm_cvtss_f32(t); #else - return rint(f); + return rint(f); #endif } static inline auto roundCurrent(double f) { #ifdef SIMD_SUPPORT - auto t = _mm_set_sd(f); - t = _mm_round_sd(t, t, _MM_FROUND_CUR_DIRECTION); - return _mm_cvtsd_f64(t); + auto t = _mm_set_sd(f); + t = _mm_round_sd(t, t, _MM_FROUND_CUR_DIRECTION); + return _mm_cvtsd_f64(t); #else - return rint(f); + return rint(f); #endif } static inline auto roundFloor(float f) { #ifdef SIMD_SUPPORT - __m128 t = _mm_set_ss(f); - t = _mm_round_ss(t, t, _MM_FROUND_TO_NEG_INF); - return _mm_cvtss_f32(t); + __m128 t = _mm_set_ss(f); + t = _mm_round_ss(t, t, _MM_FROUND_TO_NEG_INF); + return _mm_cvtss_f32(t); #else - return floor(f); + return floor(f); #endif } static inline auto roundFloor(double f) { #ifdef SIMD_SUPPORT - __m128d t = _mm_set_sd(f); - t = _mm_round_sd(t, t, _MM_FROUND_TO_NEG_INF); - return _mm_cvtsd_f64(t); + __m128d t = _mm_set_sd(f); + t = _mm_round_sd(t, t, _MM_FROUND_TO_NEG_INF); + return _mm_cvtsd_f64(t); #else - return floor(f); + return floor(f); #endif } static inline auto roundTrunc(float f) { #ifdef SIMD_SUPPORT - __m128 t = _mm_set_ss(f); - t = _mm_round_ss(t, t, _MM_FROUND_TO_ZERO); - return _mm_cvtss_f32(t); + __m128 t = _mm_set_ss(f); + t = _mm_round_ss(t, t, _MM_FROUND_TO_ZERO); + return _mm_cvtss_f32(t); #else - return trunc(f); + return trunc(f); #endif } static inline auto roundTrunc(double f) { #ifdef SIMD_SUPPORT - __m128d t = _mm_set_sd(f); - t = _mm_round_sd(t, t, _MM_FROUND_TO_ZERO); - return _mm_cvtsd_f64(t); + __m128d t = _mm_set_sd(f); + t = _mm_round_sd(t, t, _MM_FROUND_TO_ZERO); + return _mm_cvtsd_f64(t); #else - return trunc(f); + return trunc(f); #endif } -} // namespace Util +} // namespace ircolib diff --git a/external/ircolib/log.hpp b/external/ircolib/log.hpp new file mode 100644 index 0000000..e96caeb --- /dev/null +++ b/external/ircolib/log.hpp @@ -0,0 +1,61 @@ +#pragma once +#include +#include + +namespace ircolib { +enum LogLevel : u8 { Trace, Debug, Info, Warn, Error, Always }; + +constexpr LogLevel globalLogLevel = Warn; + +template +void panic(std::format_string fmt, Args &&...args) { + std::print("[FATAL] "); + std::println(fmt, std::forward(args)...); + exit(1); +} + +template +void error(std::format_string fmt, Args &&...args) { + if (LogLevel::Error >= globalLogLevel) { + std::print("[ERROR] "); + std::println(fmt, std::forward(args)...); + } +} + +template +void warn(std::format_string fmt, Args &&...args) { + if (LogLevel::Warn >= globalLogLevel) { + std::print("[WARN] "); + std::println(fmt, std::forward(args)...); + } +} + +template +void info(std::format_string fmt, Args &&...args) { + if (LogLevel::Info >= globalLogLevel) { + std::print("[INFO] "); + std::println(fmt, std::forward(args)...); + } +} + +template +void debug(std::format_string fmt, Args &&...args) { + if (LogLevel::Debug >= globalLogLevel) { + std::print("[DEBUG] "); + std::println(fmt, std::forward(args)...); + } +} + +template +void trace(std::format_string fmt, Args &&...args) { + if (LogLevel::Trace >= globalLogLevel) { + std::print("[TRACE] "); + std::println(fmt, std::forward(args)...); + } +} + +template +void always(std::format_string fmt, Args &&...args) { + std::println(fmt, std::forward(args)...); +} +} // namespace ircolib diff --git a/external/ircolib/mem_access.hpp b/external/ircolib/mem_access.hpp index 1b29bf3..f093607 100644 --- a/external/ircolib/mem_access.hpp +++ b/external/ircolib/mem_access.hpp @@ -1,5 +1,6 @@ #pragma once -#include +#include "types.hpp" +#include #include #include #include @@ -8,139 +9,152 @@ #include namespace ircolib { -static inline std::vector IntegralToBuffer(const std::integral auto &val) { - std::vector ret{}; - ret.resize(sizeof(val)); +static inline std::vector integral_to_buffer(const std::integral auto &val) { + std::vector ret{}; + ret.resize(sizeof(val)); - memcpy(ret.data(), &val, sizeof(val)); + memcpy(ret.data(), &val, sizeof(val)); - return ret; + return ret; } -static inline constexpr bool IsInsideRange(const std::integral auto& addr, - const std::integral auto& start, - const std::integral auto& end) { - return addr >= start && addr <= end; +static inline auto integral_to_slice(const std::integral auto &val) -> std::array { + std::array ret{}; + + memcpy(ret.data(), &val, sizeof(val)); + + return ret; +} + +static inline constexpr bool is_inside_range(const std::integral auto &addr, const std::integral auto &start, + const std::integral auto &end) { + return addr >= start && addr <= end; } template -static constexpr inline T ReadAccess(const u8 *data, const u32 index); +static constexpr inline T read_access(const u8 *data, const u32 index); template -static constexpr inline T ReadAccess(const std::vector &data, const u32 index); +static constexpr inline T read_access(const std::vector &data, const u32 index); template -static constexpr inline T ReadAccess(const std::array &data, const u32 index); +static constexpr inline T read_access(const std::array &data, const u32 index); template -static constexpr inline void WriteAccess(u8 *data, const u32 index, const T val); +static constexpr inline void write_access(u8 *data, const u32 index, const T val); template -static constexpr inline void WriteAccess(std::vector &data, const u32 index, const T val); +static constexpr inline void write_access(std::vector &data, const u32 index, const T val); template -static constexpr inline void WriteAccess(std::array &data, const u32 index, const T val); +static constexpr inline void write_access(std::array &data, const u32 index, const T val); template <> -constexpr inline u64 ReadAccess(const u8 *data, const u32 index) { - u32 hi = *reinterpret_cast(&data[index + 0]); - u32 lo = *reinterpret_cast(&data[index + 4]); - const auto& result = static_cast(hi) << 32 | static_cast(lo); - return result; +constexpr inline u64 read_access(const u8 *data, const u32 index) { + u32 hi = *reinterpret_cast(&data[index + 0]); + u32 lo = *reinterpret_cast(&data[index + 4]); + const auto &result = static_cast(hi) << 32 | static_cast(lo); + return result; } template -static constexpr inline T ReadAccess(const u8 *data, const u32 index) { - return *reinterpret_cast(&data[index]); +static constexpr inline T read_access(const u8 *data, const u32 index) { + return *reinterpret_cast(&data[index]); } template <> -constexpr inline u64 ReadAccess(const std::vector &data, const u32 index) { - u32 hi = *reinterpret_cast(&data[index + 0]); - u32 lo = *reinterpret_cast(&data[index + 4]); - return (static_cast(hi) << 32) | static_cast(lo); +constexpr inline u64 read_access(const std::vector &data, const u32 index) { + u32 hi = *reinterpret_cast(&data[index + 0]); + u32 lo = *reinterpret_cast(&data[index + 4]); + return (static_cast(hi) << 32) | static_cast(lo); } template -static constexpr inline T ReadAccess(const std::vector &data, const u32 index) { - return *reinterpret_cast(&data[index]); +static constexpr inline T read_access(const std::vector &data, const u32 index) { + return *reinterpret_cast(&data[index]); } template -constexpr inline u64 ReadAccess(const std::array &data, const u32 index) { - u32 hi = *reinterpret_cast(&data[index + 0]); - u32 lo = *reinterpret_cast(&data[index + 4]); - return static_cast(hi) << 32 | static_cast(lo); +static constexpr inline u64 read_access(const std::array &data, const u32 index) { + u32 hi = *reinterpret_cast(&data[index + 0]); + u32 lo = *reinterpret_cast(&data[index + 4]); + return static_cast(hi) << 32 | static_cast(lo); } template -static constexpr inline T ReadAccess(const std::array &data, const u32 index) { - return *reinterpret_cast(&data[index]); +static constexpr inline T read_access(const std::array &data, const u32 index) { + return *reinterpret_cast(&data[index]); } template -constexpr inline void WriteAccess(std::array &data, const u32 index, const u64 val) { - const u32 hi = val >> 32; - const u32 lo = val; +static constexpr inline void write_access(std::array &data, const u32 index, const u64 val) { + const u32 hi = val >> 32; + const u32 lo = val; - *reinterpret_cast(&data[index + 0]) = hi; - *reinterpret_cast(&data[index + 4]) = lo; + *reinterpret_cast(&data[index + 0]) = hi; + *reinterpret_cast(&data[index + 4]) = lo; } template -static constexpr inline void WriteAccess(std::array &data, const u32 index, const T val) { - *reinterpret_cast(&data[index]) = val; +static constexpr inline void write_access(std::array &data, const u32 index, const T val) { + *reinterpret_cast(&data[index]) = val; } template <> -constexpr inline void WriteAccess(std::vector &data, const u32 index, const u64 val) { - const u32 hi = val >> 32; - const u32 lo = val; +constexpr inline void write_access(std::vector &data, const u32 index, const u64 val) { + const u32 hi = val >> 32; + const u32 lo = val; - *reinterpret_cast(&data[index + 0]) = hi; - *reinterpret_cast(&data[index + 4]) = lo; + *reinterpret_cast(&data[index + 0]) = hi; + *reinterpret_cast(&data[index + 4]) = lo; } template -static constexpr inline void WriteAccess(std::vector &data, const u32 index, const T val) { - *reinterpret_cast(&data[index]) = val; +static constexpr inline void write_access(std::vector &data, const u32 index, const T val) { + *reinterpret_cast(&data[index]) = val; } template <> -constexpr inline void WriteAccess(u8 *data, const u32 index, const u64 val) { - const u32 hi = val >> 32; - const u32 lo = val; +constexpr inline void write_access(u8 *data, const u32 index, const u64 val) { + const u32 hi = val >> 32; + const u32 lo = val; - *reinterpret_cast(&data[index + 0]) = hi; - *reinterpret_cast(&data[index + 4]) = lo; + *reinterpret_cast(&data[index + 0]) = hi; + *reinterpret_cast(&data[index + 4]) = lo; } template -static constexpr inline void WriteAccess(u8 *data, const u32 index, const T val) { - *reinterpret_cast(&data[index]) = val; +static constexpr inline void write_access(u8 *data, const u32 index, const T val) { + *reinterpret_cast(&data[index]) = val; } template -static constexpr inline void SwapBuffer(std::vector &data) { - for (size_t i = 0; i < data.size(); i += sizeof(T)) { - const T original = *reinterpret_cast(&data[i]); - *reinterpret_cast(&data[i]) = std::byteswap(original); - } +static constexpr inline void swap_buffer(std::vector &data) { + for (u32 i = 0; i < data.size(); i += sizeof(T)) { + const T original = *reinterpret_cast(&data[i]); + *reinterpret_cast(&data[i]) = std::byteswap(original); + } } template -static constexpr inline void SwapBuffer(std::array &data) { - for (size_t i = 0; i < data.size(); i += sizeof(T)) { - const T original = *reinterpret_cast(&data[i]); - *reinterpret_cast(&data[i]) = std::byteswap(original); - } +static constexpr inline void swap_buffer(std::array &data) { + for (u32 i = 0; i < data.size(); i += sizeof(T)) { + const T original = *reinterpret_cast(&data[i]); + *reinterpret_cast(&data[i]) = std::byteswap(original); + } +} + +template +static constexpr inline void swap_buffer(u8 *data, u32 size) { + for (u32 i = 0; i < size; i += sizeof(T)) { + const T original = *reinterpret_cast(&data[i]); + *reinterpret_cast(&data[i]) = std::byteswap(original); + } } #ifdef _WIN32 -inline void *aligned_alloc(const size_t alignment, const size_t size) { return _aligned_malloc(size, alignment); } +inline void *aligned_alloc(const u32 alignment, const u32 size) { return _aligned_malloc(size, alignment); } inline void aligned_free(void *ptr) { _aligned_free(ptr); } #else -inline void *aligned_alloc(const size_t alignment, const size_t size) { - return std::aligned_alloc(alignment, size); -} +inline void *aligned_alloc(const u32 alignment, const u32 size) { return std::aligned_alloc(alignment, size); } inline void aligned_free(void *ptr) { std::free(ptr); } #endif -} // namespace Util +} // namespace ircolib diff --git a/external/ircolib/types.hpp b/external/ircolib/types.hpp index 9752f90..522230e 100644 --- a/external/ircolib/types.hpp +++ b/external/ircolib/types.hpp @@ -1,5 +1,11 @@ #pragma once #include +#ifdef USE_NEON +#include +#else +#include +#include +#endif namespace ircolib { using u8 = uint8_t; @@ -10,4 +16,33 @@ using s8 = int8_t; using s16 = int16_t; using s32 = int32_t; using s64 = int64_t; -} \ No newline at end of file + +template +static constexpr bool is_bit_set(const T &val) { + return val & (1 << bit); +} + +template +static constexpr void set_bit(T &val) { + val |= 1 << bit; +} + +template +inline bool is_bit_set(const T &val, const u32 &bit) { + return val & (1 << bit); +} + +template +inline void set_bit(T &val, const u32 &bit) { + val |= 1 << bit; +} + +template +inline void clear_bit(T &val, const u32 &bit) { + val &= ~(1 << bit); +} +} // namespace ircolib + +constexpr ircolib::u32 operator""_kib(const unsigned long long v) { return v * 1024; } +constexpr ircolib::u32 operator""_mib(const unsigned long long v) { return v * 1024 * 1024; } +constexpr ircolib::u32 operator""_gib(const unsigned long long v) { return v * 1024 * 1024 * 1024; } diff --git a/external/parallel-rdp/ParallelRDPWrapper.cpp b/external/parallel-rdp/ParallelRDPWrapper.cpp index 5632709..0d92a9b 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.cpp +++ b/external/parallel-rdp/ParallelRDPWrapper.cpp @@ -38,7 +38,7 @@ Util::IntrusivePtr InitVulkanContext(WSIPlatform *platform, const unsig if (!new_context->init_instance(instance_ext.data(), instance_ext.size(), CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT)) { - panic("Failed to create Vulkan instance.\n"); + ircolib::panic("Failed to create Vulkan instance.\n"); } const auto tmp_surface = platform->create_surface(new_context->get_instance(), VK_NULL_HANDLE); @@ -51,7 +51,7 @@ Util::IntrusivePtr InitVulkanContext(WSIPlatform *platform, const unsig } if (!ret) { - panic("Failed to create Vulkan device.\n"); + ircolib::panic("Failed to create Vulkan device.\n"); } return new_context; @@ -67,15 +67,15 @@ void ParallelRDP::LoadWSIPlatform(const std::shared_ptr &wsi_platfo if (constexpr Context::SystemHandles handles; !wsi->init_from_existing_context(InitVulkanContext(wsi_platform.get(), 1, handles, instanceFactory))) { - panic("Failed to initialize WSI: init_from_existing_context() failed"); + ircolib::panic("Failed to initialize WSI: init_from_existing_context() failed"); } if (!wsi->init_device()) { - panic("Failed to initialize WSI: init_device() failed"); + ircolib::panic("Failed to initialize WSI: init_device() failed"); } if (!wsi->init_surface_swapchain()) { - panic("Failed to initialize WSI: init_surface_swapchain() failed"); + ircolib::panic("Failed to initialize WSI: init_surface_swapchain() failed"); } windowInfo = newWindowInfo; @@ -124,7 +124,8 @@ void ParallelRDP::Init(const std::shared_ptr &wsiPlatform, offset, 8 * 1024 * 1024, 4 * 1024 * 1024, flags); if (!command_processor->device_is_supported()) { - panic("This device probably does not support 8/16-bit storage. Make sure you're using up-to-date drivers!"); + ircolib::panic( + "This device probably does not support 8/16-bit storage. Make sure you're using up-to-date drivers!"); } } diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index ba091c1..87c7cde 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -56,7 +56,7 @@ u32 Core::StepCPU() { if (cpuType == CachedInterpreter) return interpreter.ExecuteCached() + regs.PopStalledCycles(); - panic("Invalid CPU type?"); + ircolib::panic("Invalid CPU type?"); } void Core::StepRSP(const u32 cpuCycles) { diff --git a/src/backend/GameDB.cpp b/src/backend/GameDB.cpp index 2d019ef..4549cf9 100644 --- a/src/backend/GameDB.cpp +++ b/src/backend/GameDB.cpp @@ -73,15 +73,15 @@ std::string GameDB::match(ROM &rom) { return result; } - info("Matched code for {}, but not region! Game supposedly exists in regions [{}] but this image has " - "region {}", - name, regions, rom.header.countryCode); + ircolib::info("Matched code for {}, but not region! Game supposedly exists in regions [{}] but this image has " + "region {}", + name, regions, rom.header.countryCode); rom.saveType = saveType; rom.gameNameDB = name; return result; } - info("Did not match any Game DB entries. Code: {} Region: {}", rom.code, rom.header.countryCode); + ircolib::info("Did not match any Game DB entries. Code: {} Region: {}", rom.code, rom.header.countryCode); rom.gameNameDB = ""; rom.saveType = SAVE_NONE; diff --git a/src/backend/Netplay.cpp b/src/backend/Netplay.cpp index 9ef2f8d..72d0bf7 100644 --- a/src/backend/Netplay.cpp +++ b/src/backend/Netplay.cpp @@ -1,6 +1,6 @@ #include #include #include -#include +#include namespace Netplay {} diff --git a/src/backend/RomHelpers.hpp b/src/backend/RomHelpers.hpp index f0d372c..c3f8b33 100644 --- a/src/backend/RomHelpers.hpp +++ b/src/backend/RomHelpers.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace Util { #define Z64 0x80371200 @@ -13,7 +13,7 @@ FORCE_INLINE void SwapN64Rom(std::vector &rom, u32 endianness) { if (endianness >> 24 != 0x80) { if ((endianness & 0xFF) != 0x80) { if ((endianness >> 16 & 0xff) != 0x80) { - panic("Unrecognized rom endianness"); + ircolib::panic("Unrecognized rom endianness"); return; } else { altByteShift = 12; @@ -29,20 +29,20 @@ FORCE_INLINE void SwapN64Rom(std::vector &rom, u32 endianness) { switch (endianness) { case V64: - ircolib::SwapBuffer(rom); + ircolib::swap_buffer(rom); if constexpr (!toBE) - ircolib::SwapBuffer(rom); + ircolib::swap_buffer(rom); break; case N64: if constexpr (toBE) - ircolib::SwapBuffer(rom); + ircolib::swap_buffer(rom); break; case Z64: if constexpr (!toBE) - ircolib::SwapBuffer(rom); + ircolib::swap_buffer(rom); break; default: - panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!"); + ircolib::panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!"); } } } // namespace Util diff --git a/src/backend/Scheduler.cpp b/src/backend/Scheduler.cpp index 45c0bc4..126471f 100644 --- a/src/backend/Scheduler.cpp +++ b/src/backend/Scheduler.cpp @@ -63,10 +63,10 @@ void Scheduler::HandleEvents() { case NONE: break; case IMPOSSIBLE: - panic("Impossible scheduler event happened"); + ircolib::panic("Impossible scheduler event happened"); return; default: - panic("Unknown scheduler event type {}", static_cast(type)); + ircolib::panic("Unknown scheduler event type {}", static_cast(type)); return; } events.pop(); diff --git a/src/backend/Scheduler.hpp b/src/backend/Scheduler.hpp index 5cb5b25..548fa6f 100644 --- a/src/backend/Scheduler.hpp +++ b/src/backend/Scheduler.hpp @@ -1,7 +1,8 @@ #pragma once #include -#include +#include #include +#include enum EventType { NONE, PAUSE, STOP, RESET, PI_BUS_WRITE_COMPLETE, PI_DMA_COMPLETE, SI_DMA, IMPOSSIBLE }; diff --git a/src/backend/core/Disassembler.cpp b/src/backend/core/Disassembler.cpp index 5ff5fe8..ef79a49 100644 --- a/src/backend/core/Disassembler.cpp +++ b/src/backend/core/Disassembler.cpp @@ -3,75 +3,69 @@ #include Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 address, const u32 instruction) const { - cs_insn *insn; - const auto bytes = ircolib::IntegralToBuffer(std::byteswap(instruction)); - const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn); + cs_insn *insn; + const auto bytes = ircolib::integral_to_buffer(std::byteswap(instruction)); + const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn); - if (count <= 0) - return {}; + if (count <= 0) + return {}; - DisassemblyResult result{true, std::format("0x{:016X}:\t{}\t{}", insn[0].address, insn[0].mnemonic, insn[0].op_str)}; + DisassemblyResult result{true, + std::format("0x{:016X}:\t{}\t{}", insn[0].address, insn[0].mnemonic, insn[0].op_str)}; - cs_free(insn, count); + cs_free(insn, count); - return result; + return result; } [[nodiscard]] Disassembler::DisassemblyResult Disassembler::Disassemble(const u32 address) const { - u32 paddr; - if(!n64::Core::GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr)) - return DisassemblyResult{false, ""}; + u32 paddr; + if (!n64::Core::GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr)) + return DisassemblyResult{false, ""}; - u32 instruction = n64::Core::GetMem().Read(paddr); - - return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction); + u32 instruction = n64::Core::GetMem().Read(paddr); + + return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction); } Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 address, const u32 instruction) const { - n64::Core& core = n64::Core::GetInstance(); - cs_insn *insn; - const auto bytes = ircolib::IntegralToBuffer(std::byteswap(instruction)); - const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn); + n64::Core &core = n64::Core::GetInstance(); + cs_insn *insn; + const auto bytes = ircolib::integral_to_buffer(std::byteswap(instruction)); + const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn); - if (count <= 0) - return {}; + if (count <= 0) + return {}; - DisassemblyResult result{true}; - result.address = insn[0].address; - result.mnemonic = insn[0].mnemonic; + DisassemblyResult result{true}; + result.address = insn[0].address; + result.mnemonic = insn[0].mnemonic; - result.full += std::format("0x{:016X}", result.address) + ":\t"; - result.full += result.mnemonic + "\t"; + result.full += std::format("0x{:016X}", result.address) + ":\t"; + result.full += result.mnemonic + "\t"; - const cs_detail *details = insn[0].detail; - auto formatOperand = [&](const cs_mips_op &operand) { - switch (operand.type) { - case MIPS_OP_IMM: - return DisassemblyResult::Operand{ - 0xffcbf1ae, - std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm) - }; - case MIPS_OP_MEM: - return DisassemblyResult::Operand{ - 0xffaef1c3, - std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp) - }; - case MIPS_OP_REG: - return DisassemblyResult::Operand{ - 0xffaef1eb, - std::format("{}", cs_reg_name(handle, operand.reg)) - }; - default: - return DisassemblyResult::Operand { 0xff808080, "" }; + const cs_detail *details = insn[0].detail; + auto formatOperand = [&](const cs_mips_op &operand) { + switch (operand.type) { + case MIPS_OP_IMM: + return DisassemblyResult::Operand{0xffcbf1ae, + std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm)}; + case MIPS_OP_MEM: + return DisassemblyResult::Operand{ + 0xffaef1c3, std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp)}; + case MIPS_OP_REG: + return DisassemblyResult::Operand{0xffaef1eb, std::format("{}", cs_reg_name(handle, operand.reg))}; + default: + return DisassemblyResult::Operand{0xff808080, ""}; + } + }; + + for (u8 i = 0; i < details->mips.op_count && i < 3; i++) { + result.ops[i] = formatOperand(details->mips.operands[i]); + result.full += result.ops[i].str + "\t"; } - }; - for (u8 i = 0; i < details->mips.op_count && i < 3; i++) { - result.ops[i] = formatOperand(details->mips.operands[i]); - result.full += result.ops[i].str + "\t"; - } + cs_free(insn, count); - cs_free(insn, count); - - return result; -} \ No newline at end of file + return result; +} diff --git a/src/backend/core/Disassembler.hpp b/src/backend/core/Disassembler.hpp index 256e7e3..179ea3c 100644 --- a/src/backend/core/Disassembler.hpp +++ b/src/backend/core/Disassembler.hpp @@ -1,8 +1,9 @@ #pragma once #include -#include +#include #include #include +#include struct Disassembler { struct DisassemblyResult { @@ -32,11 +33,11 @@ struct Disassembler { explicit Disassembler(const bool rsp) : rsp(rsp) { if (cs_open(CS_ARCH_MIPS, static_cast((rsp ? CS_MODE_32 : CS_MODE_64) | CS_MODE_BIG_ENDIAN), &handle) != CS_ERR_OK) { - panic("Could not initialize {} disassembler!", rsp ? "RSP" : "CPU"); + ircolib::panic("Could not initialize {} disassembler!", rsp ? "RSP" : "CPU"); } if (cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON) != CS_ERR_OK) { - warn("Could not enable disassembler's details!"); + ircolib::warn("Could not enable disassembler's details!"); details = false; } } diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index e799858..f34bf24 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -126,7 +126,7 @@ bool Interpreter::DetectIdleLoop(const std::array(load.rs()) + offset; u32 paddr; if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) - panic("Failed to translate load address in DetectIdleLoop"); + ircolib::panic("Failed to translate load address in DetectIdleLoop"); return isLoad && delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 && load.rt() == delay.rs() && delay.rt() == branch.rs() && IsAddressMMIOorRDRAM(paddr); @@ -148,7 +148,7 @@ bool Interpreter::DetectIdleLoop(const std::array{}, sramPath); - sramVec = ircolib::ReadFileBinary(sramPath); + ircolib::write_file_binary(std::array{}, sramPath); + sramVec = ircolib::read_file_binary(sramPath); } if (sramVec.size() != SRAM_SIZE) { - error("[Mem]: Save data is corrupt or has unexpected size! (it's {} KiB)", sramVec.size() / 1024); + ircolib::error("[Mem]: Save data is corrupt or has unexpected size! (it's {} KiB)", sramVec.size() / 1024); return; } saveData = mio::make_mmap_sink(sramPath, err); if (err) { - error(R"([Mem]: Could not create file sink for save data @ "{}")", sramPath); + ircolib::error(R"([Mem]: Could not create file sink for save data @ "{}")", sramPath); } } } @@ -84,7 +84,7 @@ FORCE_INLINE void SetROMCIC(u32 checksum, ROM &rom) { rom.cicType = CIC_NUS_6106_7106; break; default: - warn("Could not determine CIC TYPE! Checksum: 0x{:08X} is unknown!", checksum); + ircolib::warn("Could not determine CIC TYPE! Checksum: 0x{:08X} is unknown!", checksum); rom.cicType = UNKNOWN_CIC_TYPE; break; } @@ -104,7 +104,7 @@ ROM Mem::LoadROM(const bool isArchive, const std::string &filename) { buf = Util::OpenROM(filename, sizeAdjusted); } - endianness = std::byteswap(ircolib::ReadAccess(buf, 0)); + endianness = std::byteswap(ircolib::read_access(buf, 0)); Util::SwapN64Rom(buf, endianness); std::ranges::copy(buf, res.cart.begin()); @@ -130,7 +130,7 @@ ROM Mem::LoadROM(const bool isArchive, const std::string &filename) { const u32 checksum = SDL_crc32(0, &res.cart[0x40], 0x9C0); SetROMCIC(checksum, res); - endianness = std::byteswap(ircolib::ReadAccess(res.cart, 0)); + endianness = std::byteswap(ircolib::read_access(res.cart, 0)); Util::SwapN64Rom(res.cart, endianness); res.pal = IsROMPAL(res); return res; @@ -141,38 +141,38 @@ u8 Mem::Read(const u32 paddr) { n64::Registers ®s = n64::Core::GetRegs(); const SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM(paddr); - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; return src[BYTE_ADDRESS(paddr & 0xfff)]; } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) return mmio.pi.BusRead(paddr); - if (ircolib::IsInsideRange(paddr, AI_REGION_START, AI_REGION_END)) { + if (ircolib::is_inside_range(paddr, AI_REGION_START, AI_REGION_END)) { const u32 w = mmio.ai.Read(paddr & ~3); const int offs = 3 - (paddr & 3); return w >> offs * 8 & 0xff; } - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) { - panic("8-bit read access from MMIO addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) { + ircolib::panic("8-bit read access from MMIO addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); return 0; } - if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) + if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) return si.pif.bootrom[BYTE_ADDRESS(paddr) - PIF_ROM_REGION_START]; - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) return si.pif.ram[paddr - PIF_RAM_REGION_START]; - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return 0; - panic("8-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); + ircolib::panic("8-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); return 0; } @@ -181,29 +181,29 @@ u16 Mem::Read(const u32 paddr) { n64::Registers ®s = n64::Core::GetRegs(); const SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM(paddr); - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; - return ircolib::ReadAccess(src, HALF_ADDRESS(paddr & 0xfff)); + return ircolib::read_access(src, HALF_ADDRESS(paddr & 0xfff)); } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) return mmio.pi.BusRead(paddr); - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) return mmio.Read(paddr); - if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) - return ircolib::ReadAccess(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) - return std::byteswap(ircolib::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) + return ircolib::read_access(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) + return std::byteswap(ircolib::read_access(si.pif.ram, paddr - PIF_RAM_REGION_START)); + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return 0; - panic("16-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); + ircolib::panic("16-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); return 0; } @@ -212,30 +212,30 @@ u32 Mem::Read(const u32 paddr) { n64::Registers ®s = n64::Core::GetRegs(); const SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM(paddr); - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; - return ircolib::ReadAccess(src, paddr & 0xfff); + return ircolib::read_access(src, paddr & 0xfff); } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) return mmio.pi.BusRead(paddr); - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) return mmio.Read(paddr); - if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) - return ircolib::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) - return std::byteswap(ircolib::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) + return ircolib::read_access(si.pif.bootrom, paddr - PIF_ROM_REGION_START); + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) + return std::byteswap(ircolib::read_access(si.pif.ram, paddr - PIF_RAM_REGION_START)); + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return 0; - panic("32-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); + ircolib::panic("32-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); return 0; } @@ -244,30 +244,30 @@ u64 Mem::Read(const u32 paddr) { n64::Registers ®s = n64::Core::GetRegs(); const SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM(paddr); - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; - return ircolib::ReadAccess(src, paddr & 0xfff); + return ircolib::read_access(src, paddr & 0xfff); } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) return mmio.pi.BusRead(paddr); - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) return mmio.Read(paddr); - if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) - return ircolib::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) - return std::byteswap(ircolib::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END)) + return ircolib::read_access(si.pif.bootrom, paddr - PIF_ROM_REGION_START); + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) + return std::byteswap(ircolib::read_access(si.pif.ram, paddr - PIF_RAM_REGION_START)); + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return 0; - panic("64-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); + ircolib::panic("64-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc); return 0; } @@ -276,45 +276,46 @@ void Mem::Write(u32 paddr, u32 val) { n64::Registers ®s = n64::Core::GetRegs(); SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { val = val << (8 * (3 - (paddr & 3))); bool is_imem = paddr & 0x1000; auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem; paddr = (paddr & 0xFFF) & ~3; - ircolib::WriteAccess(dest, paddr, val); + ircolib::write_access(dest, paddr, val); return; } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { - trace("BusWrite @ {:08X} = {:02X}", paddr, val); + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { + ircolib::trace("BusWrite @ {:08X} = {:02X}", paddr, val); mmio.pi.BusWrite(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) - panic("MMIO Write!"); + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) + ircolib::panic("MMIO Write!"); - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { val = val << (8 * (3 - (paddr & 3))); paddr = (paddr - PIF_RAM_REGION_START) & ~3; - ircolib::WriteAccess(si.pif.ram, paddr, std::byteswap(val)); + ircolib::write_access(si.pif.ram, paddr, std::byteswap(val)); si.pif.ProcessCommands(); return; } - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return; - panic("Unimplemented 8-bit write at address {:08X} with value {:02X} (PC = {:016X})", paddr, val, (u64)regs.pc); + ircolib::panic("Unimplemented 8-bit write at address {:08X} with value {:02X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } template <> @@ -322,45 +323,46 @@ void Mem::Write(u32 paddr, u32 val) { n64::Registers ®s = n64::Core::GetRegs(); SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { val = val << (16 * !(paddr & 2)); bool is_imem = paddr & 0x1000; auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem; paddr = (paddr & 0xFFF) & ~3; - ircolib::WriteAccess(dest, paddr, val); + ircolib::write_access(dest, paddr, val); return; } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { - trace("BusWrite @ {:08X} = {:04X}", paddr, val); + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { + ircolib::trace("BusWrite @ {:08X} = {:04X}", paddr, val); mmio.pi.BusWrite(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) - panic("MMIO Write!"); + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) + ircolib::panic("MMIO Write!"); - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { val = val << (16 * !(paddr & 2)); paddr &= ~3; - ircolib::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val)); + ircolib::write_access(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val)); si.pif.ProcessCommands(); return; } - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return; - panic("Unimplemented 16-bit write at address {:08X} with value {:04X} (PC = {:016X})", paddr, val, (u64)regs.pc); + ircolib::panic("Unimplemented 16-bit write at address {:08X} with value {:04X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } template <> @@ -368,85 +370,87 @@ void Mem::Write(const u32 paddr, const u32 val) { n64::Registers ®s = n64::Core::GetRegs(); SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { bool is_imem = paddr & 0x1000; auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem; - ircolib::WriteAccess(dest, paddr & 0xfff, val); + ircolib::write_access(dest, paddr & 0xfff, val); return; } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { - trace("BusWrite @ {:08X} = {:08X}", paddr, val); + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { + ircolib::trace("BusWrite @ {:08X} = {:08X}", paddr, val); mmio.pi.BusWrite(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) { + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) { mmio.Write(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { - ircolib::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val)); + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { + ircolib::write_access(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val)); si.pif.ProcessCommands(); return; } - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return; - panic("Unimplemented 32-bit write at address {:08X} with value {:08X} (PC = {:016X})", paddr, val, (u64)regs.pc); + ircolib::panic("Unimplemented 32-bit write at address {:08X} with value {:08X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } void Mem::Write(const u32 paddr, u64 val) { n64::Registers ®s = n64::Core::GetRegs(); SI &si = mmio.si; - if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { + if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { + if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { bool is_imem = paddr & 0x1000; auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem; val >>= 32; - ircolib::WriteAccess(dest, paddr & 0xfff, val); + ircolib::write_access(dest, paddr & 0xfff, val); return; } - if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { - trace("BusWrite @ {:08X} = {:016X}", paddr, val); + if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) { + ircolib::trace("BusWrite @ {:08X} = {:016X}", paddr, val); mmio.pi.BusWrite(paddr, val); return; } - if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) - panic("MMIO Write!"); + if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) + ircolib::panic("MMIO Write!"); - if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { - ircolib::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val)); + if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) { + ircolib::write_access(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val)); si.pif.ProcessCommands(); return; } - if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused - ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) || - ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) || - ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || - ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4)) + if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused + ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) || + ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) || + ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) || + ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4)) return; - panic("Unimplemented 64-bit write at address {:08X} with value {:016X} (PC = {:016X})", paddr, val, (u64)regs.pc); + ircolib::panic("Unimplemented 64-bit write at address {:08X} with value {:016X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } template <> @@ -456,14 +460,14 @@ u32 Mem::BackupRead(const u32 addr) { return 0; case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); + ircolib::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); return 0; case SAVE_FLASH_1m: return flash.Read(addr); case SAVE_SRAM_256k: return 0xFFFFFFFF; default: - panic("Backup read word with unknown save type"); + ircolib::panic("Backup read word with unknown save type"); } } @@ -474,7 +478,7 @@ u8 Mem::BackupRead(const u32 addr) { return 0; case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); + ircolib::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); return 0; case SAVE_FLASH_1m: return flash.Read(addr); @@ -483,10 +487,10 @@ u8 Mem::BackupRead(const u32 addr) { assert(addr < saveData.size()); return saveData[addr]; } else { - panic("Invalid backup Read if save data is not initialized"); + ircolib::panic("Invalid backup Read if save data is not initialized"); } default: - panic("Backup read word with unknown save type"); + ircolib::panic("Backup read word with unknown save type"); } } @@ -494,18 +498,18 @@ template <> void Mem::BackupWrite(const u32 addr, const u32 val) { switch (rom.saveType) { case SAVE_NONE: - warn("Accessing cartridge with save type SAVE_NONE in write word"); + ircolib::warn("Accessing cartridge with save type SAVE_NONE in write word"); break; case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - panic("Accessing cartridge with save type SAVE_EEPROM in write word"); + ircolib::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); case SAVE_FLASH_1m: flash.Write(addr, val); break; case SAVE_SRAM_256k: break; default: - panic("Backup read word with unknown save type"); + ircolib::panic("Backup read word with unknown save type"); } } @@ -513,11 +517,11 @@ template <> void Mem::BackupWrite(const u32 addr, const u8 val) { switch (rom.saveType) { case SAVE_NONE: - warn("Accessing cartridge with save type SAVE_NONE in write word"); + ircolib::warn("Accessing cartridge with save type SAVE_NONE in write word"); break; case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - panic("Accessing cartridge with save type SAVE_EEPROM in write word"); + ircolib::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); case SAVE_FLASH_1m: flash.Write(addr, val); break; @@ -526,11 +530,11 @@ void Mem::BackupWrite(const u32 addr, const u8 val) { assert(addr < saveData.size()); saveData[addr] = val; } else { - panic("Invalid backup Write if save data is not initialized"); + ircolib::panic("Invalid backup Write if save data is not initialized"); } break; default: - panic("Backup read word with unknown save type"); + ircolib::panic("Backup read word with unknown save type"); } } } // namespace n64 diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index a6039c2..6513986 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -100,22 +100,22 @@ struct Mem { std::vector temp{}; temp.resize(size); std::copy(mmio.rdp.rdram.begin() + start, mmio.rdp.rdram.begin() + size - 1, temp.begin()); - ircolib::SwapBuffer(temp); - ircolib::WriteFileBinary(temp, "rdram.bin"); + ircolib::swap_buffer(temp); + ircolib::write_file_binary(temp, "rdram.bin"); } FORCE_INLINE void DumpIMEM() const { std::array temp{}; std::ranges::copy(mmio.rsp.imem, temp.begin()); - ircolib::SwapBuffer(temp); - ircolib::WriteFileBinary(temp, "imem.bin"); + ircolib::swap_buffer(temp); + ircolib::write_file_binary(temp, "imem.bin"); } FORCE_INLINE void DumpDMEM() const { std::array temp{}; std::ranges::copy(mmio.rsp.dmem, temp.begin()); - ircolib::SwapBuffer(temp); - ircolib::WriteFileBinary(temp, "dmem.bin"); + ircolib::swap_buffer(temp); + ircolib::write_file_binary(temp, "dmem.bin"); } MMIO mmio; diff --git a/src/backend/core/RDP.cpp b/src/backend/core/RDP.cpp index 02a72a8..f8687c3 100644 --- a/src/backend/core/RDP.cpp +++ b/src/backend/core/RDP.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -25,21 +25,21 @@ void RDP::WriteRDRAM(const size_t idx, const u8 v) { template <> void RDP::WriteRDRAM(const size_t idx, const u16 v) { if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] { - ircolib::WriteAccess(rdram, real, v); + ircolib::write_access(rdram, real, v); } } template <> void RDP::WriteRDRAM(const size_t idx, const u32 v) { if (idx < RDRAM_SIZE) [[likely]] { - ircolib::WriteAccess(rdram, idx, v); + ircolib::write_access(rdram, idx, v); } } template <> void RDP::WriteRDRAM(const size_t idx, const u64 v) { if (idx < RDRAM_SIZE) [[likely]] { - ircolib::WriteAccess(rdram, idx, v); + ircolib::write_access(rdram, idx, v); } } @@ -54,7 +54,7 @@ u8 RDP::ReadRDRAM(const size_t idx) { template <> u16 RDP::ReadRDRAM(const size_t idx) { if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] - return ircolib::ReadAccess(rdram, real); + return ircolib::read_access(rdram, real); return 0; } @@ -62,7 +62,7 @@ u16 RDP::ReadRDRAM(const size_t idx) { template <> u32 RDP::ReadRDRAM(const size_t idx) { if (idx < RDRAM_SIZE) [[likely]] - return ircolib::ReadAccess(rdram, idx); + return ircolib::read_access(rdram, idx); return 0; } @@ -70,7 +70,7 @@ u32 RDP::ReadRDRAM(const size_t idx) { template <> u64 RDP::ReadRDRAM(const size_t idx) { if (idx < RDRAM_SIZE) [[likely]] - return ircolib::ReadAccess(rdram, idx); + return ircolib::read_access(rdram, idx); return 0; } @@ -98,7 +98,7 @@ auto RDP::Read(const u32 addr) const -> u32 { case 0x0410001C: return dpc.tmem; default: - panic("Unhandled DP Command Registers read (addr: {:08X})", addr); + ircolib::panic("Unhandled DP Command Registers read (addr: {:08X})", addr); } return 0; @@ -116,7 +116,7 @@ void RDP::Write(const u32 addr, const u32 val) { WriteStatus(val); break; default: - panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})", addr, val); + ircolib::panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})", addr, val); } } @@ -216,13 +216,13 @@ void RDP::RunCommand() { return; if (len + remaining_cmds * 4 > COMMAND_BUFFER_SIZE) { - panic("Too many RDP commands"); + ircolib::panic("Too many RDP commands"); return; } if (dpc.status.xbusDmemDma) { for (int i = 0; i < len; i += 4) { - const u32 cmd = ircolib::ReadAccess(mem.mmio.rsp.dmem, current + i & 0xFFF); + const u32 cmd = ircolib::read_access(mem.mmio.rsp.dmem, current + i & 0xFFF); cmd_buf[remaining_cmds + (i >> 2)] = cmd; } } else { @@ -231,7 +231,7 @@ void RDP::RunCommand() { } for (int i = 0; i < len; i += 4) { - const u32 cmd = ircolib::ReadAccess(rdram, current + i); + const u32 cmd = ircolib::read_access(rdram, current + i); cmd_buf[remaining_cmds + (i >> 2)] = cmd; } } diff --git a/src/backend/core/RSP.cpp b/src/backend/core/RSP.cpp index 128d746..9fcbb73 100644 --- a/src/backend/core/RSP.cpp +++ b/src/backend/core/RSP.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace n64 { RSP::RSP() { Reset(); } @@ -53,8 +53,8 @@ auto RSP::Read(const u32 addr) -> u32 { { auto ®s = Core::GetRegs(); - panic("Unimplemented SP register read {:08X} (cpu pc: 0x{:016X}, rsp pc: 0x{:04X}, ra: 0x{:016X})", addr, - (u64)regs.oldPC, pc & 0xffc, (u64)regs.gpr[31]); + ircolib::panic("Unimplemented SP register read {:08X} (cpu pc: 0x{:016X}, rsp pc: 0x{:04X}, ra: 0x{:016X})", + addr, (u64)regs.oldPC, pc & 0xffc, (u64)regs.gpr[31]); } } } @@ -111,13 +111,13 @@ void RSP::DMA() { u32 mem_address = spDMASPAddr.address & 0xFF8; u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8; - trace("SP DMA from RSP to RDRAM (size: {} B, {:08X} to {:08X})", length, mem_address, dram_address); + ircolib::trace("SP DMA from RSP to RDRAM (size: {} B, {:08X} to {:08X})", length, mem_address, dram_address); for (u32 i = 0; i < spDMALen.count + 1; i++) { for (u32 j = 0; j < length; j++) { mem.mmio.rdp.WriteRDRAM(BYTE_ADDRESS(dram_address + j), src[(mem_address + j) & DMEM_DSIZE]); } - + const int skip = i == spDMALen.count ? 0 : spDMALen.skip; dram_address += (length + skip); @@ -125,7 +125,7 @@ void RSP::DMA() { mem_address += length; mem_address &= 0xFF8; } - trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address); + ircolib::trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address); lastSuccessfulSPAddr.address = mem_address; lastSuccessfulSPAddr.bank = spDMASPAddr.bank; @@ -145,7 +145,7 @@ void RSP::DMA() { u32 mem_address = spDMASPAddr.address & 0xFF8; u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8; - trace("SP DMA from RDRAM to RSP (size: {} B, {:08X} to {:08X})", length, dram_address, mem_address); + ircolib::trace("SP DMA from RDRAM to RSP (size: {} B, {:08X} to {:08X})", length, dram_address, mem_address); for (u32 i = 0; i < spDMALen.count + 1; i++) { for (u32 j = 0; j < length; j++) { @@ -159,7 +159,7 @@ void RSP::DMA() { mem_address += length; mem_address &= 0xFF8; } - trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address); + ircolib::trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address); lastSuccessfulSPAddr.address = mem_address; lastSuccessfulSPAddr.bank = spDMASPAddr.bank; @@ -195,7 +195,7 @@ void RSP::Write(const u32 addr, const u32 val) { } break; default: - panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, val); + ircolib::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, val); } } } // namespace n64 diff --git a/src/backend/core/RSP.hpp b/src/backend/core/RSP.hpp index 85142ef..eea1901 100644 --- a/src/backend/core/RSP.hpp +++ b/src/backend/core/RSP.hpp @@ -150,7 +150,7 @@ struct RSP { FORCE_INLINE void Step() { gpr[0] = 0; - const u32 instr = ircolib::ReadAccess(imem, pc & IMEM_DSIZE); + const u32 instr = ircolib::read_access(imem, pc & IMEM_DSIZE); oldPC = pc & 0xFFC; pc = nextPC & 0xFFC; nextPC += 4; diff --git a/src/backend/core/interpreter/cop0instructions.cpp b/src/backend/core/interpreter/cop0instructions.cpp index 5c2f5ce..22468f1 100644 --- a/src/backend/core/interpreter/cop0instructions.cpp +++ b/src/backend/core/interpreter/cop0instructions.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include namespace n64 { @@ -42,11 +42,12 @@ void Cop0::eret() { void Cop0::tlbr() { - if (index.i >= 32) { - panic("TLBR with TLB index {}", index.i); + auto i = index.i; + if (i >= 32) { + ircolib::panic("TLBR with TLB index {}", i); } - const TLBEntry entry = tlb[index.i]; + const TLBEntry entry = tlb[i]; entryHi.raw = entry.entryHi.raw; entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF; @@ -64,7 +65,7 @@ void Cop0::tlbw(const int index_) { page_mask.mask = top | (top >> 1); if (index_ >= 32) { - panic("TLBWI with TLB index {}", index_); + ircolib::panic("TLBWI with TLB index {}", index_); } tlb[index_].entryHi.raw = entryHi.raw; diff --git a/src/backend/core/interpreter/cop1instructions.cpp b/src/backend/core/interpreter/cop1instructions.cpp index 5e7aac9..aa2d948 100644 --- a/src/backend/core/interpreter/cop1instructions.cpp +++ b/src/backend/core/interpreter/cop1instructions.cpp @@ -555,7 +555,7 @@ void Cop1::cfc1(const Instruction instr) { val = fcr31.read(); break; default: - panic("Undefined CFC1 with rd != 0 or 31"); + ircolib::panic("Undefined CFC1 with rd != 0 or 31"); } regs.Write(instr.rt(), val); } @@ -604,7 +604,7 @@ void Cop1::ctc1(const Instruction instr) { } break; default: - panic("Undefined CTC1 with rd != 0 or 31"); + ircolib::panic("Undefined CTC1 with rd != 0 or 31"); } } diff --git a/src/backend/core/interpreter/decode.cpp b/src/backend/core/interpreter/decode.cpp index ee5765b..eeb4bd5 100644 --- a/src/backend/core/interpreter/decode.cpp +++ b/src/backend/core/interpreter/decode.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include namespace n64 { @@ -164,8 +164,8 @@ void Interpreter::special(const Instruction instr) { dsra32(instr); break; default: - panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi, - instr.instr.opcode.special_lo, instr.instr.raw, static_cast(regs.oldPC)); + ircolib::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi, + instr.instr.opcode.special_lo, instr.instr.raw, static_cast(regs.oldPC)); } } @@ -215,8 +215,8 @@ void Interpreter::regimm(const Instruction instr) { bllink(instr, regs.Read(instr.rs()) >= 0); break; default: - panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi, - instr.instr.opcode.regimm_lo, u32(instr), static_cast(regs.oldPC)); + ircolib::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi, + instr.instr.opcode.regimm_lo, u32(instr), static_cast(regs.oldPC)); } } @@ -327,7 +327,7 @@ void Interpreter::DecodeExecute(const Instruction instr) { bl(instr, regs.cop1.fcr31.compare); break; default: - panic("Undefined BC COP1 {:02X}", instr.cop_rt()); + ircolib::panic("Undefined BC COP1 {:02X}", instr.cop_rt()); } return; } @@ -450,8 +450,8 @@ void Interpreter::DecodeExecute(const Instruction instr) { sd(instr); break; default: - panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr), - static_cast(regs.oldPC)); + ircolib::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr), + static_cast(regs.oldPC)); } } } // namespace n64 diff --git a/src/backend/core/interpreter/instructions.cpp b/src/backend/core/interpreter/instructions.cpp index e4a58f5..c9ea248 100644 --- a/src/backend/core/interpreter/instructions.cpp +++ b/src/backend/core/interpreter/instructions.cpp @@ -876,7 +876,7 @@ void Interpreter::cache(const Instruction instr) { u32 ptag = GetPhysicalAddressPTag(paddr); if (type > 1) - panic("Unknown cache type {}", type); + ircolib::panic("Unknown cache type {}", type); if (type == 0) return CacheTypeInstruction(op, vaddr, paddr, ptag); @@ -905,7 +905,7 @@ void Interpreter::CacheTypeInstruction(const u8 op, const u64 vaddr, const u32 p icache.WriteBack(vaddr, paddr, ptag); break; default: - panic("Unimplemented icache op 0b{:03b}", op); + ircolib::panic("Unimplemented icache op 0b{:03b}", op); } } @@ -941,7 +941,7 @@ void Interpreter::CacheTypeData(const u8 op, const u64 vaddr, const u32 paddr, c dcache.WriteBack(vaddr, paddr, ptag); break; default: - panic("Unimplemented dcache op 0b{:03b}", op); + ircolib::panic("Unimplemented dcache op 0b{:03b}", op); } }*/ } // namespace n64 diff --git a/src/backend/core/mem/Flash.cpp b/src/backend/core/mem/Flash.cpp index a84c998..5330eb5 100644 --- a/src/backend/core/mem/Flash.cpp +++ b/src/backend/core/mem/Flash.cpp @@ -28,32 +28,32 @@ void Flash::Load(SaveType saveType, const std::string &path) { if (saveData.is_mapped()) { saveData.sync(error); if (error) { - panic("Could not sync {}", flashPath); + ircolib::panic("Could not sync {}", flashPath); } saveData.unmap(); } - auto flashVec = ircolib::ReadFileBinary(flashPath); + auto flashVec = ircolib::read_file_binary(flashPath); if (flashVec.empty()) { std::vector dummy{}; dummy.resize(FLASH_SIZE); - ircolib::WriteFileBinary(dummy, flashPath); - flashVec = ircolib::ReadFileBinary(flashPath); + ircolib::write_file_binary(dummy, flashPath); + flashVec = ircolib::read_file_binary(flashPath); } if (flashVec.size() != FLASH_SIZE) { - panic("Corrupt SRAM!"); + ircolib::panic("Corrupt SRAM!"); } saveData = mio::make_mmap_sink(flashPath, error); if (error) { - panic("Could not make mmap {}", flashPath); + ircolib::panic("Could not make mmap {}", flashPath); } } } void Flash::CommandExecute() const { - trace("Flash::CommandExecute"); + ircolib::trace("Flash::CommandExecute"); switch (state) { case FlashState::Idle: break; @@ -63,7 +63,7 @@ void Flash::CommandExecute() const { saveData[eraseOffs + i] = 0xFF; } } else { - panic("Accessing flash when not mapped!"); + ircolib::panic("Accessing flash when not mapped!"); } break; case FlashState::Write: @@ -72,11 +72,11 @@ void Flash::CommandExecute() const { saveData[writeOffs + i] = writeBuf[i]; } } else { - panic("Accessing flash when not mapped!"); + ircolib::panic("Accessing flash when not mapped!"); } break; case FlashState::Read: - panic("Execute command when flash in read state"); + ircolib::panic("Execute command when flash in read state"); break; case FlashState::Status: break; @@ -134,10 +134,10 @@ void Flash::Write(u32 index, u32 val) { CommandRead(); break; default: - warn("Invalid flash command: {:02X}", cmd); + ircolib::warn("Invalid flash command: {:02X}", cmd); } } else { - warn("Flash Write of {:08X} @ {:08X}", val, index); + ircolib::warn("Flash Write of {:08X} @ {:08X}", val, index); } } @@ -145,19 +145,19 @@ template <> void Flash::Write(u32 index, u8 val) { switch (state) { case FlashState::Idle: - panic("Invalid FlashState::Idle with Write"); + ircolib::panic("Invalid FlashState::Idle with Write"); case FlashState::Status: - panic("Invalid FlashState::Status with Write"); + ircolib::panic("Invalid FlashState::Status with Write"); case FlashState::Erase: - panic("Invalid FlashState::Erase with Write"); + ircolib::panic("Invalid FlashState::Erase with Write"); case FlashState::Read: - panic("Invalid FlashState::Read with Write"); + ircolib::panic("Invalid FlashState::Read with Write"); case FlashState::Write: assert(index <= 0x7F && "Out of range flash Write8"); writeBuf[index] = val; break; default: - warn("Invalid flash state on Write: {:02X}", static_cast(state)); + ircolib::warn("Invalid flash state on Write: {:02X}", static_cast(state)); } } @@ -165,27 +165,27 @@ template <> u8 Flash::Read(const u32 index) const { switch (state) { case FlashState::Idle: - panic("Flash read byte while in state FLASH_STATE_IDLE"); + ircolib::panic("Flash read byte while in state FLASH_STATE_IDLE"); case FlashState::Write: - panic("Flash read byte while in state FLASH_STATE_WRITE"); + ircolib::panic("Flash read byte while in state FLASH_STATE_WRITE"); case FlashState::Read: if (saveData.is_mapped()) { const u8 value = saveData[index]; - trace("Flash read byte in state read: index {:08X} = {:02X}", index, value); + ircolib::trace("Flash read byte in state read: index {:08X} = {:02X}", index, value); return value; } - panic("Accessing flash when not mapped!"); + ircolib::panic("Accessing flash when not mapped!"); case FlashState::Status: { const u32 offset = (7 - (index % 8)) * 8; const u8 value = (status >> offset) & 0xFF; - trace("Flash read byte in state status: index {:08X} = {:02X}", index, value); + ircolib::trace("Flash read byte in state status: index {:08X} = {:02X}", index, value); return value; } default: - panic("Flash read byte while in unknown state"); + ircolib::panic("Flash read byte while in unknown state"); return 0; } } diff --git a/src/backend/core/mem/Utils.hpp b/src/backend/core/mem/Utils.hpp index c2775d8..218076d 100644 --- a/src/backend/core/mem/Utils.hpp +++ b/src/backend/core/mem/Utils.hpp @@ -5,11 +5,11 @@ namespace n64 { static bool IsAddressMMIOorRDRAM(u32 addr) { - if (ircolib::IsInsideRange(addr, RDRAM_REGION_START, RDRAM_REGION_END)) + if (ircolib::is_inside_range(addr, RDRAM_REGION_START, RDRAM_REGION_END)) return true; - if (ircolib::IsInsideRange(addr, MMIO_REGION_START_1, MMIO_REGION_END_1) || - ircolib::IsInsideRange(addr, MMIO_REGION_START_2, MMIO_REGION_END_2)) + if (ircolib::is_inside_range(addr, MMIO_REGION_START_1, MMIO_REGION_END_1) || + ircolib::is_inside_range(addr, MMIO_REGION_START_2, MMIO_REGION_END_2)) return true; return false; diff --git a/src/backend/core/mmio/AI.cpp b/src/backend/core/mmio/AI.cpp index 2914b29..5c20217 100644 --- a/src/backend/core/mmio/AI.cpp +++ b/src/backend/core/mmio/AI.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include namespace n64 { @@ -76,7 +76,7 @@ void AI::Write(const u32 addr, const u32 val) { dac.precision = bitrate + 1; break; default: - panic("Unhandled AI write at addr {:08X} with val {:08X}", addr, val); + ircolib::panic("Unhandled AI write at addr {:08X} with val {:08X}", addr, val); } } diff --git a/src/backend/core/mmio/Audio.cpp b/src/backend/core/mmio/Audio.cpp index 61e13d3..68819c0 100644 --- a/src/backend/core/mmio/Audio.cpp +++ b/src/backend/core/mmio/Audio.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include namespace n64 { @@ -9,49 +9,49 @@ namespace n64 { #define BYTES_PER_HALF_SECOND (((float)AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE) AudioDevice::AudioDevice() { - audioStreamMutex = SDL_CreateMutex(); - if (!audioStreamMutex) { - panic("Unable to initialize audio mutex: {}", SDL_GetError()); - } + audioStreamMutex = SDL_CreateMutex(); + if (!audioStreamMutex) { + ircolib::panic("Unable to initialize audio mutex: {}", SDL_GetError()); + } - SDL_InitSubSystem(SDL_INIT_AUDIO); - request = {SYSTEM_SAMPLE_FORMAT, 2, AUDIO_SAMPLE_RATE}; + SDL_InitSubSystem(SDL_INIT_AUDIO); + request = {SYSTEM_SAMPLE_FORMAT, 2, AUDIO_SAMPLE_RATE}; - audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr); - if (!audioStream) { - panic("Unable to create audio stream: {}", SDL_GetError()); - } + audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr); + if (!audioStream) { + ircolib::panic("Unable to create audio stream: {}", SDL_GetError()); + } } void AudioDevice::PushSample(const float left, const float volumeL, const float right, const float volumeR) { - const float adjustedL = left * volumeL; - const float adjustedR = right * volumeR; - const float samples[]{adjustedL, adjustedR}; + const float adjustedL = left * volumeL; + const float adjustedR = right * volumeR; + const float samples[]{adjustedL, adjustedR}; - if (const auto availableBytes = static_cast(SDL_GetAudioStreamAvailable(audioStream)); - availableBytes <= BYTES_PER_HALF_SECOND) { - SDL_PutAudioStreamData(audioStream, samples, 2 * SYSTEM_SAMPLE_SIZE); - } + if (const auto availableBytes = static_cast(SDL_GetAudioStreamAvailable(audioStream)); + availableBytes <= BYTES_PER_HALF_SECOND) { + SDL_PutAudioStreamData(audioStream, samples, 2 * SYSTEM_SAMPLE_SIZE); + } - if (!running) { - SDL_ResumeAudioStreamDevice(audioStream); - running = true; - } + if (!running) { + SDL_ResumeAudioStreamDevice(audioStream); + running = true; + } } void AudioDevice::AdjustSampleRate(int sampleRate) { - LockMutex(); - SDL_DestroyAudioStream(audioStream); + LockMutex(); + SDL_DestroyAudioStream(audioStream); - if (sampleRate < 4000) { // hack for Animal Forest. It requests a frequency of 3000-something. Weird asf - sampleRate *= 4000.f / static_cast(sampleRate); - } - request = {SYSTEM_SAMPLE_FORMAT, 2, sampleRate}; + if (sampleRate < 4000) { // hack for Animal Forest. It requests a frequency of 3000-something. Weird asf + sampleRate *= 4000.f / static_cast(sampleRate); + } + request = {SYSTEM_SAMPLE_FORMAT, 2, sampleRate}; - audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr); - if (!audioStream) { - panic("Unable to create audio stream: {}", SDL_GetError()); - } - UnlockMutex(); + audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr); + if (!audioStream) { + ircolib::panic("Unable to create audio stream: {}", SDL_GetError()); + } + UnlockMutex(); } } // namespace n64 diff --git a/src/backend/core/mmio/MI.cpp b/src/backend/core/mmio/MI.cpp index c55b6fd..976200d 100644 --- a/src/backend/core/mmio/MI.cpp +++ b/src/backend/core/mmio/MI.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #define MI_VERSION_REG 0x02020102 @@ -8,58 +8,58 @@ namespace n64 { MI::MI() { Reset(); } void MI::Reset() { - intrMask.raw = 0; - intr.raw = 0; - mode.raw = 0; + intrMask.raw = 0; + intr.raw = 0; + mode.raw = 0; } auto MI::Read(u32 paddr) const -> u32 { - switch (paddr & 0xF) { - case 0x0: - return mode.raw & 0x3FF; - case 0x4: - return MI_VERSION_REG; - case 0x8: - return intr.raw & 0x3F; - case 0xC: - return intrMask.raw & 0x3F; - default: - panic("Unhandled MI[{:08X}] read", paddr); - } + switch (paddr & 0xF) { + case 0x0: + return mode.raw & 0x3FF; + case 0x4: + return MI_VERSION_REG; + case 0x8: + return intr.raw & 0x3F; + case 0xC: + return intrMask.raw & 0x3F; + default: + ircolib::panic("Unhandled MI[{:08X}] read", paddr); + } } void MI::Write(u32 paddr, u32 val) { - switch (paddr & 0xF) { //-----------sc-cscs-cvvv-vvvv - case 0x0: // ----|----|----|----|--uu|deer|rccc|cccc - mode.repeatCount = val & 0x7F; - mode.repeat = val & 0x100 ? 1 : val & 0x80 ? 0 : mode.repeat; - mode.ebus = val & 0x400 ? 1 : val & 0x200 ? 0 : mode.ebus; - mode.upper = val & 0x2000 ? 1 : val & 0x1000 ? 0 : mode.upper; - if(val & 0x800) { - InterruptLower(Interrupt::DP); + switch (paddr & 0xF) { //-----------sc-cscs-cvvv-vvvv + case 0x0: // ----|----|----|----|--uu|deer|rccc|cccc + mode.repeatCount = val & 0x7F; + mode.repeat = val & 0x100 ? 1 : val & 0x80 ? 0 : mode.repeat; + mode.ebus = val & 0x400 ? 1 : val & 0x200 ? 0 : mode.ebus; + mode.upper = val & 0x2000 ? 1 : val & 0x1000 ? 0 : mode.upper; + if (val & 0x800) { + InterruptLower(Interrupt::DP); + } + break; + case 0x4: + case 0x8: + break; + case 0xC: + for (int bit = 0; bit < 6; bit++) { + const int clearbit = bit << 1; + const int setbit = (bit << 1) + 1; + + if (val & (1 << clearbit)) { + intrMask.raw &= ~(1 << bit); + } + + if (val & (1 << setbit)) { + intrMask.raw |= 1 << bit; + } + } + + UpdateInterrupt(); + break; + default: + ircolib::panic("Unhandled MI write @ 0x{:08X} with value 0x{:08X}", paddr, val); } - break; - case 0x4: - case 0x8: - break; - case 0xC: - for (int bit = 0; bit < 6; bit++) { - const int clearbit = bit << 1; - const int setbit = (bit << 1) + 1; - - if (val & (1 << clearbit)) { - intrMask.raw &= ~(1 << bit); - } - - if (val & (1 << setbit)) { - intrMask.raw |= 1 << bit; - } - } - - UpdateInterrupt(); - break; - default: - panic("Unhandled MI write @ 0x{:08X} with value 0x{:08X}", paddr, val); - } } } // namespace n64 diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index 3f2f1c1..42936ff 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include namespace n64 { PI::PI() { Reset(); } @@ -52,17 +52,20 @@ auto PI::BusRead(u32 addr) -> u8 { switch (addr) { case REGION_PI_UNKNOWN: mem.DumpRDRAM(); - panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " - "returning FF because it is not emulated (pc: 0x{:016X})", - addr, (u64)Core::GetRegs().oldPC); + ircolib::panic( + "Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " + "returning FF because it is not emulated (pc: 0x{:016X})", + addr, (u64)Core::GetRegs().oldPC); case REGION_PI_64DD_REG: - panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::panic( + "Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " + "returning FF because it is not emulated", + addr); case REGION_PI_64DD_ROM: - warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::warn( + "Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " + "returning FF because it is not emulated", + addr); return 0xFF; case REGION_PI_SRAM: return mem.BackupRead(addr - SREGION_PI_SRAM); @@ -71,14 +74,16 @@ auto PI::BusRead(u32 addr) -> u8 { // round to nearest 4 byte boundary, keeping old LSB const u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM; if (index >= mem.rom.cart.size()) { - warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, - index, index, mem.rom.cart.size(), mem.rom.cart.size()); + ircolib::warn( + "Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, + index, index, mem.rom.cart.size(), mem.rom.cart.size()); return 0xFF; } return mem.rom.cart[index]; } default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -91,17 +96,20 @@ auto PI::BusRead(u32 addr) -> u8 { switch (addr) { case REGION_PI_UNKNOWN: - panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::panic( + "Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " + "returning FF because it is not emulated", + addr); case REGION_PI_64DD_REG: - panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::panic( + "Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " + "returning FF because it is not emulated", + addr); case REGION_PI_64DD_ROM: - warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::warn( + "Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " + "returning FF because it is not emulated", + addr); return 0xFF; case REGION_PI_SRAM: return mem.BackupRead(addr - SREGION_PI_SRAM); @@ -111,14 +119,16 @@ auto PI::BusRead(u32 addr) -> u8 { // round to nearest 4 byte boundary, keeping old LSB const u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM; if (index >= mem.rom.cart.size()) { - warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, - index, index, mem.rom.cart.size(), mem.rom.cart.size()); + ircolib::warn( + "Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, + index, index, mem.rom.cart.size(), mem.rom.cart.size()); return 0xFF; } return mem.rom.cart[index]; } default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -127,25 +137,28 @@ void PI::BusWrite(u32 addr, u32 val) { n64::Mem &mem = n64::Core::GetMem(); switch (addr) { case REGION_PI_UNKNOWN: - panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + ircolib::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); case REGION_PI_64DD_REG: if (addr == 0x05000020) { fprintf(stderr, "%c", val); } else { - warn("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", - val, addr); + ircolib::warn( + "Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", + val, addr); } break; case REGION_PI_64DD_ROM: - panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + ircolib::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, + addr); case REGION_PI_SRAM: mem.BackupWrite(addr - SREGION_PI_SRAM, val); break; case REGION_PI_ROM: - warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + ircolib::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); break; default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -169,31 +182,35 @@ auto PI::BusRead(u32 addr) -> u16 { switch (addr) { case REGION_PI_UNKNOWN: - panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::panic( + "Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " + "returning FF because it is not emulated", + addr); case REGION_PI_64DD_REG: - panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::panic( + "Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " + "returning FF because it is not emulated", + addr); case REGION_PI_64DD_ROM: - panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::panic( + "Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " + "returning FF because it is not emulated", + addr); case REGION_PI_SRAM: - panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); + ircolib::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); case REGION_PI_ROM: { addr = (addr + 2) & ~3; const u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM; if (index > mem.rom.cart.size() - 1) { - panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, - index); + ircolib::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, + index, index); } - return ircolib::ReadAccess(mem.rom.cart, index); + return ircolib::read_access(mem.rom.cart, index); } default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -210,19 +227,22 @@ void PI::BusWrite(u32 addr, u32 val) { switch (addr) { case REGION_PI_UNKNOWN: - panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + ircolib::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); case REGION_PI_64DD_REG: - panic("Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", - val, addr); + ircolib::panic( + "Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, + addr); case REGION_PI_64DD_ROM: - panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + ircolib::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, + addr); case REGION_PI_SRAM: - panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); + ircolib::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); case REGION_PI_ROM: - warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + ircolib::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); break; default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -240,19 +260,22 @@ auto PI::BusRead(u32 addr) -> u32 { switch (addr) { case REGION_PI_UNKNOWN: - warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::warn( + "Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, " + "returning FF because it is not emulated", + addr); return 0xFF; case REGION_PI_64DD_REG: - warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::warn( + "Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, " + "returning FF because it is not emulated", + addr); return 0xFF; case REGION_PI_64DD_ROM: - warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " - "returning FF because it is not emulated", - addr); + ircolib::warn( + "Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, " + "returning FF because it is not emulated", + addr); return 0xFF; case REGION_PI_SRAM: return mem.BackupRead(addr); @@ -263,20 +286,22 @@ auto PI::BusRead(u32 addr) -> u32 { switch (addr) { case REGION_CART_ISVIEWER_BUFFER: return std::byteswap( - ircolib::ReadAccess(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER)); + ircolib::read_access(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER)); case CART_ISVIEWER_FLUSH: - panic("Read from ISViewer flush!"); + ircolib::panic("Read from ISViewer flush!"); default: break; } - warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index); + ircolib::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, + index, index); return 0; } - return ircolib::ReadAccess(mem.rom.cart, index); + return ircolib::read_access(mem.rom.cart, index); } default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -293,20 +318,21 @@ void PI::BusWrite(u32 addr, u32 val) { if (!WriteLatch(val)) [[unlikely]] { return; } - warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + ircolib::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); return; case REGION_PI_64DD_REG: if (!WriteLatch(val)) [[unlikely]] { return; } - warn("Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", - val, addr); + ircolib::warn( + "Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, + addr); return; case REGION_PI_64DD_ROM: if (!WriteLatch(val)) [[unlikely]] { return; } - warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + ircolib::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); return; case REGION_PI_SRAM: if (!WriteLatch(val)) [[unlikely]] { @@ -317,7 +343,7 @@ void PI::BusWrite(u32 addr, u32 val) { case REGION_PI_ROM: switch (addr) { case REGION_CART_ISVIEWER_BUFFER: - ircolib::WriteAccess(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER, std::byteswap(val)); + ircolib::write_access(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER, std::byteswap(val)); break; case CART_ISVIEWER_FLUSH: { @@ -327,21 +353,23 @@ void PI::BusWrite(u32 addr, u32 val) { mem.isviewer_sink << message; mem.isviewer_sink.flush(); } else { - panic("ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!", - CART_ISVIEWER_SIZE, val); + ircolib::panic( + "ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!", + CART_ISVIEWER_SIZE, val); } break; } default: if (!WriteLatch(val)) [[unlikely]] { - warn("Couldn't latch PI bus, ignoring write to REGION_PI_ROM"); + ircolib::warn("Couldn't latch PI bus, ignoring write to REGION_PI_ROM"); return; } - warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + ircolib::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); } return; default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -359,24 +387,25 @@ auto PI::BusRead(u32 addr) -> u64 { switch (addr) { case REGION_PI_UNKNOWN: - panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr); + ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr); case REGION_PI_64DD_REG: - panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr); + ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr); case REGION_PI_64DD_ROM: - panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr); + ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr); case REGION_PI_SRAM: - panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); + ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); case REGION_PI_ROM: { const u32 index = addr - SREGION_PI_ROM; if (index > mem.rom.cart.size() - 7) { // -7 because we're reading an entire dword - panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, - index); + ircolib::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, + index, index); } - return ircolib::ReadAccess(mem.rom.cart, index); + return ircolib::read_access(mem.rom.cart, index); } default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -393,18 +422,22 @@ void PI::BusWrite(u32 addr, u64 val) { switch (addr) { case REGION_PI_UNKNOWN: - panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, + addr); case REGION_PI_64DD_REG: - panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", val, addr); + ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", val, + addr); case REGION_PI_64DD_ROM: - panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, + addr); case REGION_PI_SRAM: - panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); + ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); case REGION_PI_ROM: - warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + ircolib::warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); break; default: - panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", + addr); } } @@ -451,7 +484,7 @@ auto PI::Read(u32 addr) const -> u32 { case 0x04600030: return piBsdDom2Rls; default: - panic("Unhandled PI[{:08X}] read", addr); + ircolib::panic("Unhandled PI[{:08X}] read", addr); } } @@ -465,7 +498,7 @@ u8 PI::GetDomain(const u32 address) { case REGION_PI_SRAM: return 2; default: - panic("Unknown PI domain for address {:08X}!", address); + ircolib::panic("Unknown PI domain for address {:08X}!", address); } } @@ -490,7 +523,7 @@ u32 PI::AccessTiming(const u8 domain, const u32 length) const { page_size = 1 << (piBsdDom2Pgs + 2); break; default: - panic("Unknown PI domain: {}\n", domain); + ircolib::panic("Unknown PI domain: {}\n", domain); } const uint32_t pages = static_cast(ceil(static_cast(length) / static_cast(page_size))); @@ -506,7 +539,7 @@ template <> void PI::DMA() { n64::Mem &mem = n64::Core::GetMem(); const s32 len = rdLen + 1; - trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr); + ircolib::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr); if (mem.rom.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) { cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1); } @@ -524,7 +557,7 @@ void PI::DMA() { dmaBusy = true; u64 completo = AccessTiming(GetDomain(cartAddr), len); - trace("Will complete in {} cycles", completo); + ircolib::trace("Will complete in {} cycles", completo); Scheduler::GetInstance().EnqueueRelative(completo, PI_DMA_COMPLETE); } @@ -533,7 +566,7 @@ template <> void PI::DMA() { n64::Mem &mem = n64::Core::GetMem(); const s32 len = wrLen + 1; - trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr); + ircolib::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr); if (mem.rom.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) { cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1); @@ -551,7 +584,7 @@ void PI::DMA() { dmaBusy = true; u64 completo = AccessTiming(GetDomain(cartAddr), len); - trace("Will complete in {} cycles", completo); + ircolib::trace("Will complete in {} cycles", completo); Scheduler::GetInstance().EnqueueRelative(completo, PI_DMA_COMPLETE); } @@ -603,7 +636,7 @@ void PI::Write(u32 addr, u32 val) { piBsdDom2Rls = val & 0xff; break; default: - panic("Unhandled PI[{:08X}] write ({:08X})", val, addr); + ircolib::panic("Unhandled PI[{:08X}] write ({:08X})", val, addr); } } } // namespace n64 diff --git a/src/backend/core/mmio/PIF.cpp b/src/backend/core/mmio/PIF.cpp index 62e73e6..10a56c1 100644 --- a/src/backend/core/mmio/PIF.cpp +++ b/src/backend/core/mmio/PIF.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #define MEMPAK_SIZE 32768 @@ -17,14 +17,14 @@ void PIF::Reset() { if (mempak.is_mapped()) { mempak.sync(error); if (error) { - panic("Could not sync {}", mempakPath); + ircolib::panic("Could not sync {}", mempakPath); } mempak.unmap(); } if (eeprom.is_mapped()) { eeprom.sync(error); if (error) { - panic("Could not sync {}", eepromPath); + ircolib::panic("Could not sync {}", eepromPath); } eeprom.unmap(); } @@ -48,25 +48,25 @@ void PIF::MaybeLoadMempak() { if (mempak.is_mapped()) { mempak.sync(error); if (error) { - panic("Could not sync {}", mempakPath); + ircolib::panic("Could not sync {}", mempakPath); } mempak.unmap(); } - auto mempakVec = ircolib::ReadFileBinary(mempakPath); + auto mempakVec = ircolib::read_file_binary(mempakPath); if (mempak.empty()) { - info(R"(Empty mempak, making one @ "{}" ...)", mempakPath); - ircolib::WriteFileBinary(std::array{}, mempakPath); - mempakVec = ircolib::ReadFileBinary(mempakPath); + ircolib::info(R"(Empty mempak, making one @ "{}" ...)", mempakPath); + ircolib::write_file_binary(std::array{}, mempakPath); + mempakVec = ircolib::read_file_binary(mempakPath); } if (mempakVec.size() != MEMPAK_SIZE) { - panic("Corrupt mempak!"); + ircolib::panic("Corrupt mempak!"); } mempak = mio::make_mmap_sink(mempakPath, error); if (error) { - panic("Could not open {}", mempakPath); + ircolib::panic("Could not open {}", mempakPath); } mempakOpen = true; } @@ -85,7 +85,7 @@ FORCE_INLINE size_t GetSaveSize(SaveType saveType) { case SAVE_FLASH_1m: return 131072; default: - panic("Unknown save type!"); + ircolib::panic("Unknown save type!"); } } @@ -101,28 +101,28 @@ void PIF::LoadEeprom(const SaveType saveType, const std::string &path) { if (eeprom.is_mapped()) { eeprom.sync(error); if (error) { - panic("Could not sync {}", eepromPath); + ircolib::panic("Could not sync {}", eepromPath); } eeprom.unmap(); } eepromSize = GetSaveSize(saveType); - auto eepromVec = ircolib::ReadFileBinary(eepromPath); + auto eepromVec = ircolib::read_file_binary(eepromPath); if (eepromVec.empty()) { std::vector dummy{}; dummy.resize(GetSaveSize(saveType)); - ircolib::WriteFileBinary(dummy, eepromPath); + ircolib::write_file_binary(dummy, eepromPath); eepromVec = dummy; } if (eepromVec.size() != eepromSize) { - panic("Corrupt eeprom!"); + ircolib::panic("Corrupt eeprom!"); } eeprom = mio::make_mmap_sink(eepromPath, error); if (error) { - panic("Could not open {}. Reason {}", eepromPath, error.message()); + ircolib::panic("Could not open {}. Reason {}", eepromPath, error.message()); } } } @@ -254,7 +254,7 @@ void PIF::ConfigureJoyBusFrame() { } break; default: - panic("Invalid read RTC block {}", commandStart); + ircolib::panic("Invalid read RTC block {}", commandStart); } } break; @@ -262,7 +262,7 @@ void PIF::ConfigureJoyBusFrame() { memset(res, 0, 8); break; default: - panic("Invalid PIF command: {:X}", commandIndex); + ircolib::panic("Invalid PIF command: {:X}", commandIndex); } i += commandLength + reslen; @@ -351,12 +351,12 @@ void PIF::EepromRead(const u8 *cmd, u8 *res) const { if (channel == 4) { const u8 offset = cmd[3]; if ((offset * 8) >= GetSaveSize(mem.rom.saveType)) { - panic("Out of range EEPROM read! offset: {:02X}", offset); + ircolib::panic("Out of range EEPROM read! offset: {:02X}", offset); } std::copy_n(eeprom.begin() + offset * 8, 8, res); } else { - panic("EEPROM read on bad channel {}", channel); + ircolib::panic("EEPROM read on bad channel {}", channel); } } @@ -366,14 +366,14 @@ void PIF::EepromWrite(const u8 *cmd, u8 *res) { if (channel == 4) { const u8 offset = cmd[3]; if ((offset * 8) >= GetSaveSize(mem.rom.saveType)) { - panic("Out of range EEPROM write! offset: {:02X}", offset); + ircolib::panic("Out of range EEPROM write! offset: {:02X}", offset); } std::copy_n(cmd + 4, 8, eeprom.begin() + offset * 8); res[0] = 0; // Error byte, I guess it always succeeds? } else { - panic("EEPROM write on bad channel {}", channel); + ircolib::panic("EEPROM write on bad channel {}", channel); } } @@ -384,7 +384,7 @@ void PIF::HLE(const bool pal, const CICType cicType) const { switch (cicType) { case UNKNOWN_CIC_TYPE: - warn("Unknown CIC type!"); + ircolib::warn("Unknown CIC type!"); break; case CIC_NUS_6101: regs.Write(0, 0x0000000000000000); @@ -651,7 +651,7 @@ void PIF::Execute() const { mem.Write(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); switch (cicType) { case UNKNOWN_CIC_TYPE: - warn("Unknown CIC type!"); + ircolib::warn("Unknown CIC type!"); break; case CIC_NUS_6101 ... CIC_NUS_6103_7103: mem.Write(0x318, RDRAM_SIZE); diff --git a/src/backend/core/mmio/PIF/Device.cpp b/src/backend/core/mmio/PIF/Device.cpp index db1e783..69b83eb 100644 --- a/src/backend/core/mmio/PIF/Device.cpp +++ b/src/backend/core/mmio/PIF/Device.cpp @@ -1,121 +1,121 @@ #include #include #include -#include +#include namespace n64 { void PIF::InitDevices(SaveType saveType) { - joybusDevices[0].type = JOYBUS_CONTROLLER; - joybusDevices[0].accessoryType = ACCESSORY_MEMPACK; - for (int i = 1; i < 4; i++) { // TODO: make this configurable - joybusDevices[i].type = JOYBUS_NONE; - joybusDevices[i].accessoryType = ACCESSORY_NONE; - } + joybusDevices[0].type = JOYBUS_CONTROLLER; + joybusDevices[0].accessoryType = ACCESSORY_MEMPACK; + for (int i = 1; i < 4; i++) { // TODO: make this configurable + joybusDevices[i].type = JOYBUS_NONE; + joybusDevices[i].accessoryType = ACCESSORY_NONE; + } - if (saveType == SAVE_EEPROM_4k) { - joybusDevices[4].type = JOYBUS_4KB_EEPROM; - } else if (saveType == SAVE_EEPROM_16k) { - joybusDevices[4].type = JOYBUS_16KB_EEPROM; - } else { - joybusDevices[4].type = JOYBUS_NONE; - } - joybusDevices[5].type = JOYBUS_NONE; + if (saveType == SAVE_EEPROM_4k) { + joybusDevices[4].type = JOYBUS_4KB_EEPROM; + } else if (saveType == SAVE_EEPROM_16k) { + joybusDevices[4].type = JOYBUS_16KB_EEPROM; + } else { + joybusDevices[4].type = JOYBUS_NONE; + } + joybusDevices[5].type = JOYBUS_NONE; } void PIF::ControllerID(u8 *res) const { - if (channel < 6) { - switch (joybusDevices[channel].type) { - case JOYBUS_NONE: - res[0] = 0x00; - res[1] = 0x00; - res[2] = 0x00; - break; - case JOYBUS_CONTROLLER: - res[0] = 0x05; - res[1] = 0x00; - res[2] = joybusDevices[channel].accessoryType != ACCESSORY_NONE ? 0x01 : 0x02; - break; - case JOYBUS_DANCEPAD: - res[0] = 0x05; - res[1] = 0x00; - res[2] = 0x00; - break; - case JOYBUS_VRU: - res[0] = 0x00; - res[1] = 0x01; - res[2] = 0x00; - break; - case JOYBUS_MOUSE: - res[0] = 0x02; - res[1] = 0x00; - res[2] = 0x00; - break; - case JOYBUS_RANDNET_KEYBOARD: - res[0] = 0x00; - res[1] = 0x02; - res[2] = 0x00; - break; - case JOYBUS_DENSHA_DE_GO: - res[0] = 0x20; - res[1] = 0x04; - res[2] = 0x00; - break; - case JOYBUS_4KB_EEPROM: - res[0] = 0x00; - res[1] = 0x80; - res[2] = 0x00; - break; - case JOYBUS_16KB_EEPROM: - res[0] = 0x00; - res[1] = 0xC0; - res[2] = 0x00; - break; + if (channel < 6) { + switch (joybusDevices[channel].type) { + case JOYBUS_NONE: + res[0] = 0x00; + res[1] = 0x00; + res[2] = 0x00; + break; + case JOYBUS_CONTROLLER: + res[0] = 0x05; + res[1] = 0x00; + res[2] = joybusDevices[channel].accessoryType != ACCESSORY_NONE ? 0x01 : 0x02; + break; + case JOYBUS_DANCEPAD: + res[0] = 0x05; + res[1] = 0x00; + res[2] = 0x00; + break; + case JOYBUS_VRU: + res[0] = 0x00; + res[1] = 0x01; + res[2] = 0x00; + break; + case JOYBUS_MOUSE: + res[0] = 0x02; + res[1] = 0x00; + res[2] = 0x00; + break; + case JOYBUS_RANDNET_KEYBOARD: + res[0] = 0x00; + res[1] = 0x02; + res[2] = 0x00; + break; + case JOYBUS_DENSHA_DE_GO: + res[0] = 0x20; + res[1] = 0x04; + res[2] = 0x00; + break; + case JOYBUS_4KB_EEPROM: + res[0] = 0x00; + res[1] = 0x80; + res[2] = 0x00; + break; + case JOYBUS_16KB_EEPROM: + res[0] = 0x00; + res[1] = 0xC0; + res[2] = 0x00; + break; + } + } else { + ircolib::panic("Device ID on unknown channel {}", channel); } - } else { - panic("Device ID on unknown channel {}", channel); - } } bool PIF::ReadButtons(u8 *res) { - if (channel >= 6) { - res[0] = 0; - res[1] = 0; - res[2] = 0; - res[3] = 0; - return false; - } - - switch (joybusDevices[channel].type) { - case JOYBUS_NONE: - res[0] = 0x00; - res[1] = 0x00; - res[2] = 0x00; - res[3] = 0x00; - return false; // Device not present - case JOYBUS_4KB_EEPROM: - case JOYBUS_16KB_EEPROM: - case JOYBUS_CONTROLLER: - if (movie.IsLoaded()) { - const Controller controller = movie.NextInputs(); - res[0] = controller.byte1; - res[1] = controller.byte2; - res[2] = controller.joyX; - res[3] = controller.joyY; - } else { - res[0] = joybusDevices[channel].controller.byte1; - res[1] = joybusDevices[channel].controller.byte2; - res[2] = joybusDevices[channel].controller.joyX; - res[3] = joybusDevices[channel].controller.joyY; + if (channel >= 6) { + res[0] = 0; + res[1] = 0; + res[2] = 0; + res[3] = 0; + return false; } - return true; - case JOYBUS_DANCEPAD: - case JOYBUS_VRU: - case JOYBUS_MOUSE: - case JOYBUS_RANDNET_KEYBOARD: - case JOYBUS_DENSHA_DE_GO: - return false; - } - return true; + switch (joybusDevices[channel].type) { + case JOYBUS_NONE: + res[0] = 0x00; + res[1] = 0x00; + res[2] = 0x00; + res[3] = 0x00; + return false; // Device not present + case JOYBUS_4KB_EEPROM: + case JOYBUS_16KB_EEPROM: + case JOYBUS_CONTROLLER: + if (movie.IsLoaded()) { + const Controller controller = movie.NextInputs(); + res[0] = controller.byte1; + res[1] = controller.byte2; + res[2] = controller.joyX; + res[3] = controller.joyY; + } else { + res[0] = joybusDevices[channel].controller.byte1; + res[1] = joybusDevices[channel].controller.byte2; + res[2] = joybusDevices[channel].controller.joyX; + res[3] = joybusDevices[channel].controller.joyY; + } + return true; + case JOYBUS_DANCEPAD: + case JOYBUS_VRU: + case JOYBUS_MOUSE: + case JOYBUS_RANDNET_KEYBOARD: + case JOYBUS_DENSHA_DE_GO: + return false; + } + + return true; } } // namespace n64 diff --git a/src/backend/core/mmio/PIF/MupenMovie.cpp b/src/backend/core/mmio/PIF/MupenMovie.cpp index 46d60a6..0844cd1 100644 --- a/src/backend/core/mmio/PIF/MupenMovie.cpp +++ b/src/backend/core/mmio/PIF/MupenMovie.cpp @@ -3,136 +3,133 @@ #include #include - union TASMovieControllerData { - struct { - unsigned dpadRight : 1; - unsigned dpadLeft : 1; - unsigned dpadDown : 1; - unsigned dpadUp : 1; - unsigned start : 1; - unsigned z : 1; - unsigned b : 1; - unsigned a : 1; - unsigned cRight : 1; - unsigned cLeft : 1; - unsigned cDown : 1; - unsigned cUp : 1; - unsigned r : 1; - unsigned l : 1; - unsigned : 2; - signed analogX : 8; - signed analogY : 8; - }; - u32 raw; + struct { + unsigned dpadRight : 1; + unsigned dpadLeft : 1; + unsigned dpadDown : 1; + unsigned dpadUp : 1; + unsigned start : 1; + unsigned z : 1; + unsigned b : 1; + unsigned a : 1; + unsigned cRight : 1; + unsigned cLeft : 1; + unsigned cDown : 1; + unsigned cUp : 1; + unsigned r : 1; + unsigned l : 1; + unsigned : 2; + signed analogX : 8; + signed analogY : 8; + }; + u32 raw; } __attribute__((packed)); static_assert(sizeof(TASMovieControllerData) == 4); void MupenMovie::Load(const fs::path &path) { - filename = path.stem().string(); - loadedTasMovie = ircolib::ReadFileBinary(path.string()); - if (!IsLoaded()) { - error("Error loading movie!"); - return; - } + filename = path.stem().string(); + loadedTasMovie = ircolib::read_file_binary(path.string()); + if (!IsLoaded()) { + ircolib::error("Error loading movie!"); + return; + } - std::memcpy(&loadedTasMovieHeader, loadedTasMovie.data(), sizeof(TASMovieHeader)); + std::memcpy(&loadedTasMovieHeader, loadedTasMovie.data(), sizeof(TASMovieHeader)); - if (loadedTasMovieHeader.signature[0] != 0x4D || loadedTasMovieHeader.signature[1] != 0x36 || - loadedTasMovieHeader.signature[2] != 0x34 || loadedTasMovieHeader.signature[3] != 0x1A) { - error("Failed to load movie: incorrect signature. Are you sure this is a valid movie?"); - return; - } + if (loadedTasMovieHeader.signature[0] != 0x4D || loadedTasMovieHeader.signature[1] != 0x36 || + loadedTasMovieHeader.signature[2] != 0x34 || loadedTasMovieHeader.signature[3] != 0x1A) { + ircolib::error("Failed to load movie: incorrect signature. Are you sure this is a valid movie?"); + return; + } - if (loadedTasMovieHeader.version != 3) { - error("This movie is version {}: only version 3 is supported.", loadedTasMovieHeader.version); - return; - } + if (loadedTasMovieHeader.version != 3) { + ircolib::error("This movie is version {}: only version 3 is supported.", loadedTasMovieHeader.version); + return; + } - if (loadedTasMovieHeader.startType != 2) { - error("Movie start type is {} - only movies with a start type of 2 are supported (start at power on)", - loadedTasMovieHeader.startType); - return; - } + if (loadedTasMovieHeader.startType != 2) { + ircolib::error("Movie start type is {} - only movies with a start type of 2 are supported (start at power on)", + loadedTasMovieHeader.startType); + return; + } - info("Loaded movie '{}' ", loadedTasMovieHeader.movie_description); - info("by {}", loadedTasMovieHeader.author_name); - info("{} controller(s) connected", loadedTasMovieHeader.numControllers); + ircolib::info("Loaded movie '{}' ", loadedTasMovieHeader.movie_description); + ircolib::info("by {}", loadedTasMovieHeader.author_name); + ircolib::info("{} controller(s) connected", loadedTasMovieHeader.numControllers); - if (loadedTasMovieHeader.numControllers != 1) { - error("Currently, only movies with 1 controller connected are supported."); - return; - } + if (loadedTasMovieHeader.numControllers != 1) { + ircolib::error("Currently, only movies with 1 controller connected are supported."); + return; + } - loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header + loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header } -MupenMovie::MupenMovie(const fs::path &path) { - Load(path); -} +MupenMovie::MupenMovie(const fs::path &path) { Load(path); } void MupenMovie::Reset() { - if (!IsLoaded()) - return; + if (!IsLoaded()) + return; - loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header + loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header } FORCE_INLINE void LogController(const n64::Controller &controller) { - debug("c_right: {}", controller.cRight); - debug("c_left: {}", controller.cLeft); - debug("c_down: {}", controller.cDown); - debug("c_up: {}", controller.cUp); - debug("r: {}", controller.r); - debug("l: {}", controller.l); - debug("dp_right: {}", controller.dpRight); - debug("dp_left: {}", controller.dpLeft); - debug("dp_down: {}", controller.dpDown); - debug("dp_up: {}", controller.dpUp); - debug("z: {}", controller.z); - debug("b: {}", controller.b); - debug("a: {}", controller.a); - debug("start: {}", controller.start); - debug("joy_x: {}", controller.joyX); - debug("joy_y: {}", controller.joyY); + ircolib::debug("c_right: {}", controller.cRight); + ircolib::debug("c_left: {}", controller.cLeft); + ircolib::debug("c_down: {}", controller.cDown); + ircolib::debug("c_up: {}", controller.cUp); + ircolib::debug("r: {}", controller.r); + ircolib::debug("l: {}", controller.l); + ircolib::debug("dp_right: {}", controller.dpRight); + ircolib::debug("dp_left: {}", controller.dpLeft); + ircolib::debug("dp_down: {}", controller.dpDown); + ircolib::debug("dp_up: {}", controller.dpUp); + ircolib::debug("z: {}", controller.z); + ircolib::debug("b: {}", controller.b); + ircolib::debug("a: {}", controller.a); + ircolib::debug("start: {}", controller.start); + ircolib::debug("joy_x: {}", controller.joyX); + ircolib::debug("joy_y: {}", controller.joyY); } n64::Controller MupenMovie::NextInputs() { - if (loadedTasMovieIndex + sizeof(TASMovieControllerData) > loadedTasMovie.size()) { - loadedTasMovie.clear(); - n64::Controller emptyController{}; - return emptyController; - } + if (loadedTasMovieIndex + sizeof(TASMovieControllerData) > loadedTasMovie.size()) { + loadedTasMovie.clear(); + n64::Controller emptyController{}; + return emptyController; + } - TASMovieControllerData movieCData{}; - memcpy(&movieCData, &loadedTasMovie[loadedTasMovieIndex], sizeof(TASMovieControllerData)); + TASMovieControllerData movieCData{}; + memcpy(&movieCData, &loadedTasMovie[loadedTasMovieIndex], sizeof(TASMovieControllerData)); - loadedTasMovieIndex += sizeof(TASMovieControllerData); + loadedTasMovieIndex += sizeof(TASMovieControllerData); - n64::Controller controller{}; + n64::Controller controller{}; - controller.cRight = movieCData.cRight; - controller.cLeft = movieCData.cLeft; - controller.cDown = movieCData.cDown; - controller.cUp = movieCData.cUp; - controller.r = movieCData.r; - controller.l = movieCData.l; + controller.cRight = movieCData.cRight; + controller.cLeft = movieCData.cLeft; + controller.cDown = movieCData.cDown; + controller.cUp = movieCData.cUp; + controller.r = movieCData.r; + controller.l = movieCData.l; - controller.dpRight = movieCData.dpadRight; - controller.dpLeft = movieCData.dpadLeft; - controller.dpDown = movieCData.dpadDown; - controller.dpUp = movieCData.dpadUp; + controller.dpRight = movieCData.dpadRight; + controller.dpLeft = movieCData.dpadLeft; + controller.dpDown = movieCData.dpadDown; + controller.dpUp = movieCData.dpadUp; - controller.z = movieCData.z; - controller.b = movieCData.b; - controller.a = movieCData.a; - controller.start = movieCData.start; + controller.z = movieCData.z; + controller.b = movieCData.b; + controller.a = movieCData.a; + controller.start = movieCData.start; - controller.joyX = movieCData.analogX; - controller.joyY = movieCData.analogY; + controller.joyX = movieCData.analogX; + controller.joyY = movieCData.analogY; - LogController(controller); + LogController(controller); - return controller; + return controller; } diff --git a/src/backend/core/mmio/RI.cpp b/src/backend/core/mmio/RI.cpp index 2f41dc3..1fd727d 100644 --- a/src/backend/core/mmio/RI.cpp +++ b/src/backend/core/mmio/RI.cpp @@ -1,47 +1,47 @@ #include -#include +#include namespace n64 { RI::RI() { Reset(); } void RI::Reset() { - mode = 0xE; - config = 0x40; - select = 0x14; - refresh = 0x63634; + mode = 0xE; + config = 0x40; + select = 0x14; + refresh = 0x63634; } auto RI::Read(u32 addr) const -> u32 { - switch (addr) { - case 0x04700000: - return mode; - case 0x04700004: - return config; - case 0x0470000C: - return select; - case 0x04700010: - return refresh; - default: - panic("Unhandled RI[{:08X}] read", addr); - } + switch (addr) { + case 0x04700000: + return mode; + case 0x04700004: + return config; + case 0x0470000C: + return select; + case 0x04700010: + return refresh; + default: + ircolib::panic("Unhandled RI[{:08X}] read", addr); + } } void RI::Write(u32 addr, u32 val) { - switch (addr) { - case 0x04700000: - mode = val; - break; - case 0x04700004: - config = val; - break; - case 0x0470000C: - select = val; - break; - case 0x04700010: - refresh = val; - break; - default: - panic("Unhandled RI[{:08X}] write with val {:08X}", addr, val); - } + switch (addr) { + case 0x04700000: + mode = val; + break; + case 0x04700004: + config = val; + break; + case 0x0470000C: + select = val; + break; + case 0x04700010: + refresh = val; + break; + default: + ircolib::panic("Unhandled RI[{:08X}] write with val {:08X}", addr, val); + } } } // namespace n64 diff --git a/src/backend/core/mmio/SI.cpp b/src/backend/core/mmio/SI.cpp index 9a35327..565c8d7 100644 --- a/src/backend/core/mmio/SI.cpp +++ b/src/backend/core/mmio/SI.cpp @@ -32,7 +32,7 @@ auto SI::Read(u32 addr) const -> u32 { return val; } default: - panic("Unhandled SI[{:08X}] read", addr); + ircolib::panic("Unhandled SI[{:08X}] read", addr); } } @@ -44,7 +44,7 @@ void SI::DMA() { for (int i = 0; i < 64; i++) { mem.mmio.rdp.WriteRDRAM(dramAddr + i, pif.Read(pifAddr + i)); } - trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr); + ircolib::trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr); } // rdram -> pif @@ -54,7 +54,7 @@ void SI::DMA() { for (int i = 0; i < 64; i++) { pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM(dramAddr + i)); } - trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr); + ircolib::trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr); } void SI::DMA() { @@ -89,7 +89,7 @@ void SI::Write(u32 addr, u32 val) { mem.mmio.mi.InterruptLower(MI::Interrupt::SI); break; default: - panic("Unhandled SI[{:08X}] write ({:08X})", addr, val); + ircolib::panic("Unhandled SI[{:08X}] write ({:08X})", addr, val); } } } // namespace n64 diff --git a/src/backend/core/mmio/VI.cpp b/src/backend/core/mmio/VI.cpp index fa478e6..c8e85b6 100644 --- a/src/backend/core/mmio/VI.cpp +++ b/src/backend/core/mmio/VI.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace n64 { VI::VI() { Reset(); } @@ -55,7 +55,7 @@ u32 VI::Read(const u32 paddr) const { default: { n64::Registers ®s = n64::Core::GetRegs(); - panic("32-bit read access on unhandled VI register @ pc 0x{:016X}", u64(regs.oldPC)); + ircolib::panic("32-bit read access on unhandled VI register @ pc 0x{:016X}", u64(regs.oldPC)); return 0; } } @@ -120,7 +120,7 @@ void VI::Write(const u32 paddr, const u32 val) { case 0x0440003C: break; default: - panic("Unimplemented VI[{:08X}] write ({:08X})", paddr, val); + ircolib::panic("Unimplemented VI[{:08X}] write ({:08X})", paddr, val); } } } // namespace n64 diff --git a/src/backend/core/registers/Cop0.cpp b/src/backend/core/registers/Cop0.cpp index 5558956..b07f3f3 100644 --- a/src/backend/core/registers/Cop0.cpp +++ b/src/backend/core/registers/Cop0.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace n64 { Cop0::Cop0() { Reset(); } @@ -103,7 +103,7 @@ u32 Cop0::GetReg32(const u8 addr) { case 31: return openbus; default: - panic("Unsupported word read from COP0 register {}", addr); + ircolib::panic("Unsupported word read from COP0 register {}", addr); } } @@ -140,7 +140,7 @@ u64 Cop0::GetReg64(const u8 addr) const { case 31: return openbus; default: - panic("Unsupported dword read from COP0 register {}", addr); + ircolib::panic("Unsupported dword read from COP0 register {}", addr); } } @@ -236,7 +236,7 @@ void Cop0::SetReg32(const u8 addr, const u32 value) { case 31: break; default: - panic("Unsupported word write from COP0 register {}", addr); + ircolib::panic("Unsupported word write from COP0 register {}", addr); } } @@ -281,7 +281,7 @@ void Cop0::SetReg64(const u8 addr, const u64 value) { ErrorEPC = (s64)value; break; default: - panic("Unsupported dword write to COP0 register {}", addr); + ircolib::panic("Unsupported dword write to COP0 register {}", addr); } } @@ -387,7 +387,7 @@ void Cop0::FireException(const ExceptionCode code, const int cop, s64 pc) { } if (status.bev) { - panic("BEV bit set!"); + ircolib::panic("BEV bit set!"); } regs.SetPC32(s32(0x80000000 + vectorOffset)); @@ -408,7 +408,7 @@ void Cop0::HandleTLBException(const u64 vaddr) { Cop0::ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessType accessType) { switch (error) { case NONE: - panic("Getting TLB exception with error NONE"); + ircolib::panic("Getting TLB exception with error NONE"); case INVALID: case MISS: return accessType == LOAD ? ExceptionCode::TLBLoad : ExceptionCode::TLBStore; @@ -417,7 +417,7 @@ Cop0::ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAcc case DISALLOWED_ADDRESS: return accessType == LOAD ? ExceptionCode::AddressErrorLoad : ExceptionCode::AddressErrorStore; default: - panic("Getting TLB exception for unknown error code! ({})", static_cast(error)); + ircolib::panic("Getting TLB exception for unknown error code! ({})", static_cast(error)); return {}; } } @@ -459,14 +459,14 @@ void Cop0::decode(const Instruction instr) { } break; default: - panic("Unimplemented COP0 instruction {}", instr.cop_rs()); + ircolib::panic("Unimplemented COP0 instruction {}", instr.cop_rs()); } } template <> bool Cop0::MapVirtualAddress(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) { - if (ircolib::IsInsideRange(vaddr, START_VREGION_KUSEG, END_VREGION_KUSEG)) + if (ircolib::is_inside_range(vaddr, START_VREGION_KUSEG, END_VREGION_KUSEG)) return ProbeTLB(accessType, s64(s32(vaddr)), paddr); tlbError = DISALLOWED_ADDRESS; @@ -476,25 +476,25 @@ bool Cop0::MapVirtualAddress(const TLBAccessType accessType, const u6 template <> bool Cop0::MapVirtualAddress(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) { u8 segment = static_cast(vaddr) >> 29 & 7; - if (ircolib::IsInsideRange(segment, 0, 3) || segment == 7) + if (ircolib::is_inside_range(segment, 0, 3) || segment == 7) return ProbeTLB(accessType, static_cast(vaddr), paddr); - if (ircolib::IsInsideRange(segment, 4, 5)) { + if (ircolib::is_inside_range(segment, 4, 5)) { paddr = vaddr & 0x1FFFFFFF; return true; } if (segment == 6) - panic("Unimplemented virtual mapping in KSSEG! ({:08X})", vaddr); + ircolib::panic("Unimplemented virtual mapping in KSSEG! ({:08X})", vaddr); - panic("Should never end up in base case in MapVirtualAddress! ({:08X})", vaddr); + ircolib::panic("Should never end up in base case in MapVirtualAddress! ({:08X})", vaddr); return false; } template <> bool Cop0::MapVirtualAddress(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) { - if (ircolib::IsInsideRange(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF)) + if (ircolib::is_inside_range(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF)) return ProbeTLB(accessType, vaddr, paddr); tlbError = DISALLOWED_ADDRESS; @@ -503,19 +503,19 @@ bool Cop0::MapVirtualAddress(const TLBAccessType accessType, const u6 template <> bool Cop0::MapVirtualAddress(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) { - if (ircolib::IsInsideRange(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF) || // VREGION_XKUSEG - ircolib::IsInsideRange(vaddr, 0x4000000000000000, 0x400000FFFFFFFFFF) || // VREGION_XKSSEG - ircolib::IsInsideRange(vaddr, 0xC000000000000000, 0xC00000FF7FFFFFFF) || // VREGION_XKSEG - ircolib::IsInsideRange(vaddr, 0xFFFFFFFFE0000000, 0xFFFFFFFFFFFFFFFF)) // VREGION_CKSEG3 + if (ircolib::is_inside_range(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF) || // VREGION_XKUSEG + ircolib::is_inside_range(vaddr, 0x4000000000000000, 0x400000FFFFFFFFFF) || // VREGION_XKSSEG + ircolib::is_inside_range(vaddr, 0xC000000000000000, 0xC00000FF7FFFFFFF) || // VREGION_XKSEG + ircolib::is_inside_range(vaddr, 0xFFFFFFFFE0000000, 0xFFFFFFFFFFFFFFFF)) // VREGION_CKSEG3 return ProbeTLB(accessType, vaddr, paddr); - if (ircolib::IsInsideRange(vaddr, 0x8000000000000000, 0xBFFFFFFFFFFFFFFF)) { // VREGION_XKPHYS + if (ircolib::is_inside_range(vaddr, 0x8000000000000000, 0xBFFFFFFFFFFFFFFF)) { // VREGION_XKPHYS if (!kernelMode) - panic("Access to XKPHYS address 0x{:016X} when outside kernel mode!", vaddr); + ircolib::panic("Access to XKPHYS address 0x{:016X} when outside kernel mode!", vaddr); const u8 high_two_bits = (vaddr >> 62) & 0b11; if (high_two_bits != 0b10) - panic("Access to XKPHYS address 0x{:016X} with high two bits != 0b10!", vaddr); + ircolib::panic("Access to XKPHYS address 0x{:016X} with high two bits != 0b10!", vaddr); const u8 subsegment = (vaddr >> 59) & 0b11; bool cached = subsegment != 2; // do something with this eventually @@ -530,31 +530,31 @@ bool Cop0::MapVirtualAddress(const TLBAccessType accessType, const u return true; } - if (ircolib::IsInsideRange(vaddr, 0xFFFFFFFF80000000, 0xFFFFFFFF9FFFFFFF) || // VREGION_CKSEG0 - ircolib::IsInsideRange(vaddr, 0xFFFFFFFFA0000000, 0xFFFFFFFFBFFFFFFF)) { // VREGION_CKSEG1 + if (ircolib::is_inside_range(vaddr, 0xFFFFFFFF80000000, 0xFFFFFFFF9FFFFFFF) || // VREGION_CKSEG0 + ircolib::is_inside_range(vaddr, 0xFFFFFFFFA0000000, 0xFFFFFFFFBFFFFFFF)) { // VREGION_CKSEG1 u32 cut = u32(vaddr) >> 28; u32 num = cut == 0xA; // Identical to ksegX in 32 bit mode. // Unmapped translation. Subtract the base address of the space to get the physical address. paddr = vaddr - (cut << 28); // Implies cutting off the high 32 bits - trace("CKSEG{}: Translated 0x{:016X} to 0x{:08X}", num, vaddr, paddr); + ircolib::trace("CKSEG{}: Translated 0x{:016X} to 0x{:08X}", num, vaddr, paddr); return true; } - if (ircolib::IsInsideRange(vaddr, 0x0000010000000000, 0x3FFFFFFFFFFFFFFF) || // VREGION_XBAD1 - ircolib::IsInsideRange(vaddr, 0x4000010000000000, 0x7FFFFFFFFFFFFFFF) || // VREGION_XBAD2 - ircolib::IsInsideRange(vaddr, 0xC00000FF80000000, 0xFFFFFFFF7FFFFFFF)) { // VREGION_XBAD3 + if (ircolib::is_inside_range(vaddr, 0x0000010000000000, 0x3FFFFFFFFFFFFFFF) || // VREGION_XBAD1 + ircolib::is_inside_range(vaddr, 0x4000010000000000, 0x7FFFFFFFFFFFFFFF) || // VREGION_XBAD2 + ircolib::is_inside_range(vaddr, 0xC00000FF80000000, 0xFFFFFFFF7FFFFFFF)) { // VREGION_XBAD3 tlbError = DISALLOWED_ADDRESS; return false; } - panic("Resolving virtual address 0x{:016X} in 64 bit mode", vaddr); + ircolib::panic("Resolving virtual address 0x{:016X} in 64 bit mode", vaddr); return false; // just to silence warning } bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) { if (supervisorMode) - panic("Supervisor mode memory access"); + ircolib::panic("Supervisor mode memory access"); if (is64BitAddressing) [[unlikely]] { if (kernelMode) [[likely]] @@ -562,7 +562,7 @@ bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) if (userMode) return MapVirtualAddress(accessType, vaddr, paddr); - panic("Unknown mode! This should never happen!"); + ircolib::panic("Unknown mode! This should never happen!"); } if (kernelMode) [[likely]] @@ -570,6 +570,6 @@ bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) if (userMode) return MapVirtualAddress(accessType, vaddr, paddr); - panic("Unknown mode! This should never happen!"); + ircolib::panic("Unknown mode! This should never happen!"); } } // namespace n64 diff --git a/src/backend/core/registers/Cop0.hpp b/src/backend/core/registers/Cop0.hpp index ac0d21c..ba9475e 100644 --- a/src/backend/core/registers/Cop0.hpp +++ b/src/backend/core/registers/Cop0.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include diff --git a/src/backend/core/registers/Cop1.cpp b/src/backend/core/registers/Cop1.cpp index 98626c1..0dd8d63 100644 --- a/src/backend/core/registers/Cop1.cpp +++ b/src/backend/core/registers/Cop1.cpp @@ -1,290 +1,290 @@ #include -#include +#include namespace n64 { Cop1::Cop1() { Reset(); } void Cop1::Reset() { - fcr0 = 0xa00; - fcr31.write(0x01000800); - memset(fgr, 0, 32 * sizeof(FloatingPointReg)); + fcr0 = 0xa00; + fcr31.write(0x01000800); + memset(fgr, 0, 32 * sizeof(FloatingPointReg)); } void Cop1::decode(const Instruction instr) { - switch (instr.cop_rs()) { - // 000r_rccc - case 0x00: - mfc1(instr); - break; - case 0x01: - dmfc1(instr); - break; - case 0x02: - cfc1(instr); - break; - case 0x03: - unimplemented(); - break; - case 0x04: - mtc1(instr); - break; - case 0x05: - dmtc1(instr); - break; - case 0x06: - ctc1(instr); - break; - case 0x07: - unimplemented(); - break; - case 0x10: // s - switch (instr.cop_funct()) { + switch (instr.cop_rs()) { + // 000r_rccc case 0x00: - adds(instr); - break; + mfc1(instr); + break; case 0x01: - subs(instr); - break; + dmfc1(instr); + break; case 0x02: - muls(instr); - break; + cfc1(instr); + break; case 0x03: - divs(instr); - break; + unimplemented(); + break; case 0x04: - sqrts(instr); - break; + mtc1(instr); + break; case 0x05: - abss(instr); - break; + dmtc1(instr); + break; case 0x06: - movs(instr); - break; + ctc1(instr); + break; case 0x07: - negs(instr); - break; - case 0x08: - roundls(instr); - break; - case 0x09: - truncls(instr); - break; - case 0x0A: - ceills(instr); - break; - case 0x0B: - floorls(instr); - break; - case 0x0C: - roundws(instr); - break; - case 0x0D: - truncws(instr); - break; - case 0x0E: - ceilws(instr); - break; - case 0x0F: - floorws(instr); - break; - case 0x21: - cvtds(instr); - break; - case 0x24: - cvtws(instr); - break; - case 0x25: - cvtls(instr); - break; - case 0x30: - cf(instr); - break; - case 0x31: - cun(instr); - break; - case 0x32: - ceq(instr); - break; - case 0x33: - cueq(instr); - break; - case 0x34: - colt(instr); - break; - case 0x35: - cult(instr); - break; - case 0x36: - cole(instr); - break; - case 0x37: - cule(instr); - break; - case 0x38: - csf(instr); - break; - case 0x39: - cngle(instr); - break; - case 0x3A: - cseq(instr); - break; - case 0x3B: - cngl(instr); - break; - case 0x3C: - clt(instr); - break; - case 0x3D: - cnge(instr); - break; - case 0x3E: - cle(instr); - break; - case 0x3F: - cngt(instr); - break; + unimplemented(); + break; + case 0x10: // s + switch (instr.cop_funct()) { + case 0x00: + adds(instr); + break; + case 0x01: + subs(instr); + break; + case 0x02: + muls(instr); + break; + case 0x03: + divs(instr); + break; + case 0x04: + sqrts(instr); + break; + case 0x05: + abss(instr); + break; + case 0x06: + movs(instr); + break; + case 0x07: + negs(instr); + break; + case 0x08: + roundls(instr); + break; + case 0x09: + truncls(instr); + break; + case 0x0A: + ceills(instr); + break; + case 0x0B: + floorls(instr); + break; + case 0x0C: + roundws(instr); + break; + case 0x0D: + truncws(instr); + break; + case 0x0E: + ceilws(instr); + break; + case 0x0F: + floorws(instr); + break; + case 0x21: + cvtds(instr); + break; + case 0x24: + cvtws(instr); + break; + case 0x25: + cvtls(instr); + break; + case 0x30: + cf(instr); + break; + case 0x31: + cun(instr); + break; + case 0x32: + ceq(instr); + break; + case 0x33: + cueq(instr); + break; + case 0x34: + colt(instr); + break; + case 0x35: + cult(instr); + break; + case 0x36: + cole(instr); + break; + case 0x37: + cule(instr); + break; + case 0x38: + csf(instr); + break; + case 0x39: + cngle(instr); + break; + case 0x3A: + cseq(instr); + break; + case 0x3B: + cngl(instr); + break; + case 0x3C: + clt(instr); + break; + case 0x3D: + cnge(instr); + break; + case 0x3E: + cle(instr); + break; + case 0x3F: + cngt(instr); + break; + default: + unimplemented(); + } + break; + case 0x11: // d + switch (instr.cop_funct()) { + case 0x00: + addd(instr); + break; + case 0x01: + subd(instr); + break; + case 0x02: + muld(instr); + break; + case 0x03: + divd(instr); + break; + case 0x04: + sqrtd(instr); + break; + case 0x05: + absd(instr); + break; + case 0x06: + movd(instr); + break; + case 0x07: + negd(instr); + break; + case 0x08: + roundld(instr); + break; + case 0x09: + truncld(instr); + break; + case 0x0A: + ceilld(instr); + break; + case 0x0B: + floorld(instr); + break; + case 0x0C: + roundwd(instr); + break; + case 0x0D: + truncwd(instr); + break; + case 0x0E: + ceilwd(instr); + break; + case 0x0F: + floorwd(instr); + break; + case 0x20: + cvtsd(instr); + break; + case 0x24: + cvtwd(instr); + break; + case 0x25: + cvtld(instr); + break; + case 0x30: + cf(instr); + break; + case 0x31: + cun(instr); + break; + case 0x32: + ceq(instr); + break; + case 0x33: + cueq(instr); + break; + case 0x34: + colt(instr); + break; + case 0x35: + cult(instr); + break; + case 0x36: + cole(instr); + break; + case 0x37: + cule(instr); + break; + case 0x38: + csf(instr); + break; + case 0x39: + cngle(instr); + break; + case 0x3A: + cseq(instr); + break; + case 0x3B: + cngl(instr); + break; + case 0x3C: + clt(instr); + break; + case 0x3D: + cnge(instr); + break; + case 0x3E: + cle(instr); + break; + case 0x3F: + cngt(instr); + break; + default: + unimplemented(); + } + break; + case 0x14: // w + switch (instr.cop_funct()) { + case 0x20: + cvtsw(instr); + break; + case 0x21: + cvtdw(instr); + break; + default: + unimplemented(); + } + break; + case 0x15: // l + switch (instr.cop_funct()) { + case 0x20: + cvtsl(instr); + break; + case 0x21: + cvtdl(instr); + break; + default: + unimplemented(); + } + break; default: - unimplemented(); + ircolib::panic("Unimplemented COP1 instruction {}", instr.cop_rs()); } - break; - case 0x11: // d - switch (instr.cop_funct()) { - case 0x00: - addd(instr); - break; - case 0x01: - subd(instr); - break; - case 0x02: - muld(instr); - break; - case 0x03: - divd(instr); - break; - case 0x04: - sqrtd(instr); - break; - case 0x05: - absd(instr); - break; - case 0x06: - movd(instr); - break; - case 0x07: - negd(instr); - break; - case 0x08: - roundld(instr); - break; - case 0x09: - truncld(instr); - break; - case 0x0A: - ceilld(instr); - break; - case 0x0B: - floorld(instr); - break; - case 0x0C: - roundwd(instr); - break; - case 0x0D: - truncwd(instr); - break; - case 0x0E: - ceilwd(instr); - break; - case 0x0F: - floorwd(instr); - break; - case 0x20: - cvtsd(instr); - break; - case 0x24: - cvtwd(instr); - break; - case 0x25: - cvtld(instr); - break; - case 0x30: - cf(instr); - break; - case 0x31: - cun(instr); - break; - case 0x32: - ceq(instr); - break; - case 0x33: - cueq(instr); - break; - case 0x34: - colt(instr); - break; - case 0x35: - cult(instr); - break; - case 0x36: - cole(instr); - break; - case 0x37: - cule(instr); - break; - case 0x38: - csf(instr); - break; - case 0x39: - cngle(instr); - break; - case 0x3A: - cseq(instr); - break; - case 0x3B: - cngl(instr); - break; - case 0x3C: - clt(instr); - break; - case 0x3D: - cnge(instr); - break; - case 0x3E: - cle(instr); - break; - case 0x3F: - cngt(instr); - break; - default: - unimplemented(); - } - break; - case 0x14: // w - switch (instr.cop_funct()) { - case 0x20: - cvtsw(instr); - break; - case 0x21: - cvtdw(instr); - break; - default: - unimplemented(); - } - break; - case 0x15: // l - switch (instr.cop_funct()) { - case 0x20: - cvtsl(instr); - break; - case 0x21: - cvtdl(instr); - break; - default: - unimplemented(); - } - break; - default: - panic("Unimplemented COP1 instruction {}", instr.cop_rs()); - } } } // namespace n64 diff --git a/src/backend/core/rsp/decode.cpp b/src/backend/core/rsp/decode.cpp index b559f39..41fb613 100644 --- a/src/backend/core/rsp/decode.cpp +++ b/src/backend/core/rsp/decode.cpp @@ -1,456 +1,456 @@ #include -#include +#include namespace n64 { void RSP::special(const Instruction instr) { - MI& mi = Core::GetMem().mmio.mi; - switch (instr.cop_funct()) { - case 0x00: - if (instr != 0) { - sll(instr); + MI &mi = Core::GetMem().mmio.mi; + switch (instr.cop_funct()) { + case 0x00: + if (instr != 0) { + sll(instr); + } + break; + case 0x02: + srl(instr); + break; + case 0x03: + sra(instr); + break; + case 0x04: + sllv(instr); + break; + case 0x06: + srlv(instr); + break; + case 0x07: + srav(instr); + break; + case 0x08: + jr(instr); + break; + case 0x09: + jalr(instr); + break; + case 0x0D: + spStatus.halt = true; + steps = 0; + spStatus.broke = true; + if (spStatus.interruptOnBreak) { + mi.InterruptRaise(MI::Interrupt::SP); + } + break; + case 0x20: + case 0x21: + add(instr); + break; + case 0x22: + case 0x23: + sub(instr); + break; + case 0x24: + and_(instr); + break; + case 0x25: + or_(instr); + break; + case 0x26: + xor_(instr); + break; + case 0x27: + nor(instr); + break; + case 0x2A: + slt(instr); + break; + case 0x2B: + sltu(instr); + break; + default: + ircolib::panic("Unhandled RSP special instruction ({:06b})", instr.cop_funct()); } - break; - case 0x02: - srl(instr); - break; - case 0x03: - sra(instr); - break; - case 0x04: - sllv(instr); - break; - case 0x06: - srlv(instr); - break; - case 0x07: - srav(instr); - break; - case 0x08: - jr(instr); - break; - case 0x09: - jalr(instr); - break; - case 0x0D: - spStatus.halt = true; - steps = 0; - spStatus.broke = true; - if (spStatus.interruptOnBreak) { - mi.InterruptRaise(MI::Interrupt::SP); - } - break; - case 0x20: - case 0x21: - add(instr); - break; - case 0x22: - case 0x23: - sub(instr); - break; - case 0x24: - and_(instr); - break; - case 0x25: - or_(instr); - break; - case 0x26: - xor_(instr); - break; - case 0x27: - nor(instr); - break; - case 0x2A: - slt(instr); - break; - case 0x2B: - sltu(instr); - break; - default: - panic("Unhandled RSP special instruction ({:06b})", instr.cop_funct()); - } } void RSP::regimm(const Instruction instr) { - switch (instr.cop_rt()) { - case 0x00: - b(instr, gpr[instr.rs()] < 0); - break; - case 0x01: - b(instr, gpr[instr.rs()] >= 0); - break; - case 0x10: - blink(instr, gpr[instr.rs()] < 0); - break; - case 0x11: - blink(instr, gpr[instr.rs()] >= 0); - break; - default: - panic("Unhandled RSP regimm instruction ({:05b})", instr.cop_rt()); - } + switch (instr.cop_rt()) { + case 0x00: + b(instr, gpr[instr.rs()] < 0); + break; + case 0x01: + b(instr, gpr[instr.rs()] >= 0); + break; + case 0x10: + blink(instr, gpr[instr.rs()] < 0); + break; + case 0x11: + blink(instr, gpr[instr.rs()] >= 0); + break; + default: + ircolib::panic("Unhandled RSP regimm instruction ({:05b})", instr.cop_rt()); + } } void RSP::lwc2(const Instruction instr) { - switch (instr.rd()) { - case 0x00: - lbv(instr); - break; - case 0x01: - lsv(instr); - break; - case 0x02: - llv(instr); - break; - case 0x03: - ldv(instr); - break; - case 0x04: - lqv(instr); - break; - case 0x05: - lrv(instr); - break; - case 0x06: - lpv(instr); - break; - case 0x07: - luv(instr); - break; - case 0x08: - lhv(instr); - break; - case 0x09: - lfv(instr); - break; - case 0x0A: - break; - case 0x0B: - ltv(instr); - break; - default: - panic("Unhandled RSP LWC2 {:05b}", instr.rd()); - } + switch (instr.rd()) { + case 0x00: + lbv(instr); + break; + case 0x01: + lsv(instr); + break; + case 0x02: + llv(instr); + break; + case 0x03: + ldv(instr); + break; + case 0x04: + lqv(instr); + break; + case 0x05: + lrv(instr); + break; + case 0x06: + lpv(instr); + break; + case 0x07: + luv(instr); + break; + case 0x08: + lhv(instr); + break; + case 0x09: + lfv(instr); + break; + case 0x0A: + break; + case 0x0B: + ltv(instr); + break; + default: + ircolib::panic("Unhandled RSP LWC2 {:05b}", instr.rd()); + } } void RSP::swc2(const Instruction instr) { - switch (instr.rd()) { - case 0x00: - sbv(instr); - break; - case 0x01: - ssv(instr); - break; - case 0x02: - slv(instr); - break; - case 0x03: - sdv(instr); - break; - case 0x04: - sqv(instr); - break; - case 0x05: - srv(instr); - break; - case 0x06: - spv(instr); - break; - case 0x07: - suv(instr); - break; - case 0x08: - shv(instr); - break; - case 0x09: - sfv(instr); - break; - case 0x0A: - swv(instr); - break; - case 0x0B: - stv(instr); - break; - default: - panic("Unhandled RSP SWC2 {:05b}", instr.rd()); - } + switch (instr.rd()) { + case 0x00: + sbv(instr); + break; + case 0x01: + ssv(instr); + break; + case 0x02: + slv(instr); + break; + case 0x03: + sdv(instr); + break; + case 0x04: + sqv(instr); + break; + case 0x05: + srv(instr); + break; + case 0x06: + spv(instr); + break; + case 0x07: + suv(instr); + break; + case 0x08: + shv(instr); + break; + case 0x09: + sfv(instr); + break; + case 0x0A: + swv(instr); + break; + case 0x0B: + stv(instr); + break; + default: + ircolib::panic("Unhandled RSP SWC2 {:05b}", instr.rd()); + } } void RSP::cop2(const Instruction instr) { - switch (instr.cop_funct()) { - case 0x00: - if (instr >> 25 & 1) { - vmulf(instr); - } else { - switch (instr.cop_rs()) { - case 0x00: - mfc2(instr); + switch (instr.cop_funct()) { + case 0x00: + if (instr >> 25 & 1) { + vmulf(instr); + } else { + switch (instr.cop_rs()) { + case 0x00: + mfc2(instr); + break; + case 0x02: + cfc2(instr); + break; + case 0x04: + mtc2(instr); + break; + case 0x06: + ctc2(instr); + break; + default: + ircolib::panic("Unhandled RSP COP2 sub ({:05b})", instr.cop_rs()); + } + } break; - case 0x02: - cfc2(instr); + case 0x01: + vmulu(instr); break; - case 0x04: - mtc2(instr); + case 0x02: + vrndp(instr); break; - case 0x06: - ctc2(instr); + case 0x03: + vmulq(instr); break; - default: - panic("Unhandled RSP COP2 sub ({:05b})", instr.cop_rs()); - } + case 0x04: + vmudl(instr); + break; + case 0x05: + vmudm(instr); + break; + case 0x06: + vmudn(instr); + break; + case 0x07: + vmudh(instr); + break; + case 0x08: + vmacf(instr); + break; + case 0x09: + vmacu(instr); + break; + case 0x0A: + vrndn(instr); + break; + case 0x0B: + vmacq(instr); + break; + case 0x0C: + vmadl(instr); + break; + case 0x0D: + vmadm(instr); + break; + case 0x0E: + vmadn(instr); + break; + case 0x0F: + vmadh(instr); + break; + case 0x10: + vadd(instr); + break; + case 0x11: + vsub(instr); + break; + case 0x12: + vzero(instr); + break; + case 0x13: + vabs(instr); + break; + case 0x14: + vaddc(instr); + break; + case 0x15: + vsubc(instr); + break; + case 0x16 ... 0x1C: + case 0x1E: + case 0x1F: + case 0x2E: + case 0x2F: + vzero(instr); + break; + case 0x1D: + vsar(instr); + break; + case 0x20: + vlt(instr); + break; + case 0x21: + veq(instr); + break; + case 0x22: + vne(instr); + break; + case 0x23: + vge(instr); + break; + case 0x24: + vcl(instr); + break; + case 0x25: + vch(instr); + break; + case 0x26: + vcr(instr); + break; + case 0x27: + vmrg(instr); + break; + case 0x28: + vand(instr); + break; + case 0x29: + vnand(instr); + break; + case 0x2A: + vor(instr); + break; + case 0x2B: + vnor(instr); + break; + case 0x2C: + vxor(instr); + break; + case 0x2D: + vnxor(instr); + break; + case 0x31: + vrcpl(instr); + break; + case 0x35: + vrsql(instr); + break; + case 0x32: + case 0x36: + vrcph(instr); + break; + case 0x30: + vrcp(instr); + break; + case 0x33: + vmov(instr); + break; + case 0x34: + vrsq(instr); + break; + case 0x38 ... 0x3E: + vzero(instr); + break; + case 0x37: + case 0x3F: + break; + default: + ircolib::panic("Unhandled RSP COP2 ({:06b})", instr.cop_funct()); } - break; - case 0x01: - vmulu(instr); - break; - case 0x02: - vrndp(instr); - break; - case 0x03: - vmulq(instr); - break; - case 0x04: - vmudl(instr); - break; - case 0x05: - vmudm(instr); - break; - case 0x06: - vmudn(instr); - break; - case 0x07: - vmudh(instr); - break; - case 0x08: - vmacf(instr); - break; - case 0x09: - vmacu(instr); - break; - case 0x0A: - vrndn(instr); - break; - case 0x0B: - vmacq(instr); - break; - case 0x0C: - vmadl(instr); - break; - case 0x0D: - vmadm(instr); - break; - case 0x0E: - vmadn(instr); - break; - case 0x0F: - vmadh(instr); - break; - case 0x10: - vadd(instr); - break; - case 0x11: - vsub(instr); - break; - case 0x12: - vzero(instr); - break; - case 0x13: - vabs(instr); - break; - case 0x14: - vaddc(instr); - break; - case 0x15: - vsubc(instr); - break; - case 0x16 ... 0x1C: - case 0x1E: - case 0x1F: - case 0x2E: - case 0x2F: - vzero(instr); - break; - case 0x1D: - vsar(instr); - break; - case 0x20: - vlt(instr); - break; - case 0x21: - veq(instr); - break; - case 0x22: - vne(instr); - break; - case 0x23: - vge(instr); - break; - case 0x24: - vcl(instr); - break; - case 0x25: - vch(instr); - break; - case 0x26: - vcr(instr); - break; - case 0x27: - vmrg(instr); - break; - case 0x28: - vand(instr); - break; - case 0x29: - vnand(instr); - break; - case 0x2A: - vor(instr); - break; - case 0x2B: - vnor(instr); - break; - case 0x2C: - vxor(instr); - break; - case 0x2D: - vnxor(instr); - break; - case 0x31: - vrcpl(instr); - break; - case 0x35: - vrsql(instr); - break; - case 0x32: - case 0x36: - vrcph(instr); - break; - case 0x30: - vrcp(instr); - break; - case 0x33: - vmov(instr); - break; - case 0x34: - vrsq(instr); - break; - case 0x38 ... 0x3E: - vzero(instr); - break; - case 0x37: - case 0x3F: - break; - default: - panic("Unhandled RSP COP2 ({:06b})", instr.cop_funct()); - } } void RSP::cop0(const Instruction instr) { - if ((instr & 0x7FF) == 0) { - switch (instr.cop_rs()) { - case 0x00: - mfc0(Core::GetMem().mmio.rdp, instr); - break; - case 0x04: - mtc0(instr); - break; - default: - panic("Unhandled RSP COP0 ({:05b})", instr.cop_rs()); + if ((instr & 0x7FF) == 0) { + switch (instr.cop_rs()) { + case 0x00: + mfc0(Core::GetMem().mmio.rdp, instr); + break; + case 0x04: + mtc0(instr); + break; + default: + ircolib::panic("Unhandled RSP COP0 ({:05b})", instr.cop_rs()); + } + } else { + ircolib::panic("RSP COP0 unknown {:08X}", u32(instr)); } - } else { - panic("RSP COP0 unknown {:08X}", u32(instr)); - } } void RSP::Exec(const Instruction instr) { - Mem& mem = Core::GetMem(); - MMIO &mmio = mem.mmio; - MI &mi = mmio.mi; - switch (instr.opcode()) { - case 0x00: - special(instr); - break; - case 0x01: - regimm(instr); - break; - case 0x02: - j(instr); - break; - case 0x03: - jal(instr); - break; - case 0x04: - b(instr, gpr[instr.rt()] == gpr[instr.rs()]); - break; - case 0x05: - b(instr, gpr[instr.rt()] != gpr[instr.rs()]); - break; - case 0x06: - b(instr, gpr[instr.rs()] <= 0); - break; - case 0x07: - b(instr, gpr[instr.rs()] > 0); - break; - case 0x08: - case 0x09: - addi(instr); - break; - case 0x0A: - slti(instr); - break; - case 0x0B: - sltiu(instr); - break; - case 0x0C: - andi(instr); - break; - case 0x0D: - ori(instr); - break; - case 0x0E: - xori(instr); - break; - case 0x0F: - lui(instr); - break; - case 0x10: - cop0(instr); - break; - case 0x12: - cop2(instr); - break; - case 0x20: - lb(instr); - break; - case 0x21: - lh(instr); - break; - case 0x23: - case 0x27: - lw(instr); - break; - case 0x24: - lbu(instr); - break; - case 0x25: - lhu(instr); - break; - case 0x28: - sb(instr); - break; - case 0x29: - sh(instr); - break; - case 0x2B: - sw(instr); - break; - case 0x32: - lwc2(instr); - break; - case 0x3A: - swc2(instr); - break; - default: - mem.DumpIMEM(); - panic("Unhandled RSP instruction ({:06b}, {:04X})", instr.opcode(), oldPC); - } + Mem &mem = Core::GetMem(); + MMIO &mmio = mem.mmio; + MI &mi = mmio.mi; + switch (instr.opcode()) { + case 0x00: + special(instr); + break; + case 0x01: + regimm(instr); + break; + case 0x02: + j(instr); + break; + case 0x03: + jal(instr); + break; + case 0x04: + b(instr, gpr[instr.rt()] == gpr[instr.rs()]); + break; + case 0x05: + b(instr, gpr[instr.rt()] != gpr[instr.rs()]); + break; + case 0x06: + b(instr, gpr[instr.rs()] <= 0); + break; + case 0x07: + b(instr, gpr[instr.rs()] > 0); + break; + case 0x08: + case 0x09: + addi(instr); + break; + case 0x0A: + slti(instr); + break; + case 0x0B: + sltiu(instr); + break; + case 0x0C: + andi(instr); + break; + case 0x0D: + ori(instr); + break; + case 0x0E: + xori(instr); + break; + case 0x0F: + lui(instr); + break; + case 0x10: + cop0(instr); + break; + case 0x12: + cop2(instr); + break; + case 0x20: + lb(instr); + break; + case 0x21: + lh(instr); + break; + case 0x23: + case 0x27: + lw(instr); + break; + case 0x24: + lbu(instr); + break; + case 0x25: + lhu(instr); + break; + case 0x28: + sb(instr); + break; + case 0x29: + sh(instr); + break; + case 0x2B: + sw(instr); + break; + case 0x32: + lwc2(instr); + break; + case 0x3A: + swc2(instr); + break; + default: + mem.DumpIMEM(); + ircolib::panic("Unhandled RSP instruction ({:06b}, {:04X})", instr.opcode(), oldPC); + } } } // namespace n64 diff --git a/src/backend/core/rsp/instructions.cpp b/src/backend/core/rsp/instructions.cpp index da5af5e..c9bd56c 100644 --- a/src/backend/core/rsp/instructions.cpp +++ b/src/backend/core/rsp/instructions.cpp @@ -1,189 +1,189 @@ #include #include #include -#include +#include namespace n64 { FORCE_INLINE bool AcquireSemaphore(RSP &rsp) { - if (rsp.semaphore) { - return true; - } + if (rsp.semaphore) { + return true; + } - rsp.semaphore = true; - return false; + rsp.semaphore = true; + return false; } FORCE_INLINE void ReleaseSemaphore(RSP &rsp) { rsp.semaphore = false; } FORCE_INLINE int SignExt7bit(const u8 val, const int sa) { - const s8 sval = val << 1 & 0x80 | val; + const s8 sval = val << 1 & 0x80 | val; - const s32 sval32 = sval; - const u32 val32 = sval32; - return val32 << sa; + const s32 sval32 = sval; + const u32 val32 = sval32; + return val32 << sa; } FORCE_INLINE auto GetCop0Reg(RSP &rsp, const RDP &rdp, const u8 index) -> u32 { - switch (index) { - case 0: - return rsp.lastSuccessfulSPAddr.raw; - case 1: - return rsp.lastSuccessfulDRAMAddr.raw; - case 2: - case 3: - return rsp.spDMALen.raw; - case 4: - return rsp.spStatus.raw; - case 5: - return rsp.spStatus.dmaFull; - case 6: - return rsp.spStatus.dmaBusy; - case 7: - return AcquireSemaphore(rsp); - case 8: - return rdp.dpc.start; - case 9: - return rdp.dpc.end; - case 10: - return rdp.dpc.current; - case 11: - return rdp.dpc.status.raw; - case 12: - return rdp.dpc.clock; - case 13: - return rdp.dpc.status.cmdBusy; - case 14: - return rdp.dpc.status.pipeBusy; - case 15: - return rdp.dpc.status.tmemBusy; - default: - panic("Unhandled RSP COP0 register read at index {}", index); - return 0; - } + switch (index) { + case 0: + return rsp.lastSuccessfulSPAddr.raw; + case 1: + return rsp.lastSuccessfulDRAMAddr.raw; + case 2: + case 3: + return rsp.spDMALen.raw; + case 4: + return rsp.spStatus.raw; + case 5: + return rsp.spStatus.dmaFull; + case 6: + return rsp.spStatus.dmaBusy; + case 7: + return AcquireSemaphore(rsp); + case 8: + return rdp.dpc.start; + case 9: + return rdp.dpc.end; + case 10: + return rdp.dpc.current; + case 11: + return rdp.dpc.status.raw; + case 12: + return rdp.dpc.clock; + case 13: + return rdp.dpc.status.cmdBusy; + case 14: + return rdp.dpc.status.pipeBusy; + case 15: + return rdp.dpc.status.tmemBusy; + default: + ircolib::panic("Unhandled RSP COP0 register read at index {}", index); + return 0; + } } FORCE_INLINE void SetCop0Reg(Mem &mem, const u8 index, const u32 val) { - MMIO &mmio = mem.mmio; - RSP &rsp = mmio.rsp; - RDP &rdp = mmio.rdp; - switch (index) { - case 0: - rsp.spDMASPAddr.raw = val; - break; - case 1: - rsp.spDMADRAMAddr.raw = val; - break; - case 2: - rsp.spDMALen.raw = val; - rsp.DMA(); - break; - case 3: - rsp.spDMALen.raw = val; - rsp.DMA(); - break; - case 4: - rsp.WriteStatus(val); - break; - case 7: - if (val == 0) { - ReleaseSemaphore(rsp); - } else { - panic("Write with non-zero value to RSP_COP0_RESERVED ({})", val); + MMIO &mmio = mem.mmio; + RSP &rsp = mmio.rsp; + RDP &rdp = mmio.rdp; + switch (index) { + case 0: + rsp.spDMASPAddr.raw = val; + break; + case 1: + rsp.spDMADRAMAddr.raw = val; + break; + case 2: + rsp.spDMALen.raw = val; + rsp.DMA(); + break; + case 3: + rsp.spDMALen.raw = val; + rsp.DMA(); + break; + case 4: + rsp.WriteStatus(val); + break; + case 7: + if (val == 0) { + ReleaseSemaphore(rsp); + } else { + ircolib::panic("Write with non-zero value to RSP_COP0_RESERVED ({})", val); + } + break; + case 8: + rdp.WriteStart(val); + break; + case 9: + rdp.WriteEnd(val); + break; + case 11: + rdp.WriteStatus(val); + break; + default: + ircolib::panic("Unhandled RSP COP0 register write at index {}", index); } - break; - case 8: - rdp.WriteStart(val); - break; - case 9: - rdp.WriteEnd(val); - break; - case 11: - rdp.WriteStatus(val); - break; - default: - panic("Unhandled RSP COP0 register write at index {}", index); - } } FORCE_INLINE VPR Broadcast(const VPR &vt, const int l0, const int l1, const int l2, const int l3, const int l4, const int l5, const int l6, const int l7) { - VPR vte{}; - vte.element[ELEMENT_INDEX(0)] = vt.element[ELEMENT_INDEX(l0)]; - vte.element[ELEMENT_INDEX(1)] = vt.element[ELEMENT_INDEX(l1)]; - vte.element[ELEMENT_INDEX(2)] = vt.element[ELEMENT_INDEX(l2)]; - vte.element[ELEMENT_INDEX(3)] = vt.element[ELEMENT_INDEX(l3)]; - vte.element[ELEMENT_INDEX(4)] = vt.element[ELEMENT_INDEX(l4)]; - vte.element[ELEMENT_INDEX(5)] = vt.element[ELEMENT_INDEX(l5)]; - vte.element[ELEMENT_INDEX(6)] = vt.element[ELEMENT_INDEX(l6)]; - vte.element[ELEMENT_INDEX(7)] = vt.element[ELEMENT_INDEX(l7)]; - return vte; + VPR vte{}; + vte.element[ELEMENT_INDEX(0)] = vt.element[ELEMENT_INDEX(l0)]; + vte.element[ELEMENT_INDEX(1)] = vt.element[ELEMENT_INDEX(l1)]; + vte.element[ELEMENT_INDEX(2)] = vt.element[ELEMENT_INDEX(l2)]; + vte.element[ELEMENT_INDEX(3)] = vt.element[ELEMENT_INDEX(l3)]; + vte.element[ELEMENT_INDEX(4)] = vt.element[ELEMENT_INDEX(l4)]; + vte.element[ELEMENT_INDEX(5)] = vt.element[ELEMENT_INDEX(l5)]; + vte.element[ELEMENT_INDEX(6)] = vt.element[ELEMENT_INDEX(l6)]; + vte.element[ELEMENT_INDEX(7)] = vt.element[ELEMENT_INDEX(l7)]; + return vte; } #ifdef SIMD_SUPPORT void RSP::SetVTE(const VPR &vt, u8 e) { - e &= 0xf; - switch (e & 0xf) { - case 0 ... 1: - vte = vt; - break; - case 2: - vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xF5), 0xF5); - break; - case 3: - vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xA0), 0xA0); - break; - case 4: - vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xFF), 0xFF); - break; - case 5: - vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xAA), 0xAA); - break; - case 6: - vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0x55), 0x55); - break; - case 7: - vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0x00), 0x00); - break; - case 8 ... 15: - { - const int index = ELEMENT_INDEX(e - 8); - vte.single = _mm_set1_epi16(vt.element[index]); + e &= 0xf; + switch (e & 0xf) { + case 0 ... 1: + vte = vt; + break; + case 2: + vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xF5), 0xF5); + break; + case 3: + vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xA0), 0xA0); + break; + case 4: + vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xFF), 0xFF); + break; + case 5: + vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0xAA), 0xAA); + break; + case 6: + vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0x55), 0x55); + break; + case 7: + vte.single = _mm_shufflehi_epi16(_mm_shufflelo_epi16(vt.single, 0x00), 0x00); + break; + case 8 ... 15: + { + const int index = ELEMENT_INDEX(e - 8); + vte.single = _mm_set1_epi16(vt.element[index]); + } + break; } - break; - } } #else void RSP::SetVTE(const VPR &vt, u8 e) { - e &= 0xf; - switch (e) { - case 0 ... 1: - vte = vt; - break; - case 2 ... 3: - vte = Broadcast(vt, e - 2, e - 2, e, e, e + 2, e + 2, e + 4, e + 4); - break; - case 4 ... 7: - vte = Broadcast(vt, e - 4, e - 4, e - 4, e - 4, e, e, e, e); - break; - case 8 ... 15: - { - int index = ELEMENT_INDEX(e - 8); - for (int i = 0; i < 8; i++) { - vte.element[i] = vt.element[index]; - } + e &= 0xf; + switch (e) { + case 0 ... 1: + vte = vt; + break; + case 2 ... 3: + vte = Broadcast(vt, e - 2, e - 2, e, e, e + 2, e + 2, e + 4, e + 4); + break; + case 4 ... 7: + vte = Broadcast(vt, e - 4, e - 4, e - 4, e - 4, e, e, e, e); + break; + case 8 ... 15: + { + int index = ELEMENT_INDEX(e - 8); + for (int i = 0; i < 8; i++) { + vte.element[i] = vt.element[index]; + } + } + break; } - break; - } } #endif void RSP::add(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rs()] + gpr[instr.rt()]; } void RSP::addi(const Instruction instr) { - const s32 op1 = gpr[instr.rs()]; - const s16 op2 = instr; - const s32 result = op1 + op2; - gpr[instr.rt()] = result; + const s32 op1 = gpr[instr.rs()]; + const s16 op2 = instr; + const s32 result = op1 + op2; + gpr[instr.rt()] = result; } void RSP::and_(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rt()] & gpr[instr.rs()]; } @@ -191,217 +191,217 @@ void RSP::and_(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rt()] & gp void RSP::andi(const Instruction instr) { gpr[instr.rt()] = gpr[instr.rs()] & (u16)instr; } void RSP::cfc2(const Instruction instr) { - s16 value = 0; - switch (instr.rd() & 3) { - case 0: - value = GetVCO(); - break; - case 1: - value = GetVCC(); - break; - case 2 ... 3: - value = GetVCE(); - break; - } + s16 value = 0; + switch (instr.rd() & 3) { + case 0: + value = GetVCO(); + break; + case 1: + value = GetVCC(); + break; + case 2 ... 3: + value = GetVCE(); + break; + } - gpr[instr.rt()] = value; + gpr[instr.rt()] = value; } void RSP::ctc2(const Instruction instr) { - const u16 value = gpr[instr.rt()]; - switch (instr.rd() & 3) { - case 0: - for (int i = 0; i < 8; i++) { - vco.h.element[ELEMENT_INDEX(i)] = ((value >> (i + 8)) & 1) == 1 ? 0xFFFF : 0; - vco.l.element[ELEMENT_INDEX(i)] = ((value >> i) & 1) == 1 ? 0xFFFF : 0; + const u16 value = gpr[instr.rt()]; + switch (instr.rd() & 3) { + case 0: + for (int i = 0; i < 8; i++) { + vco.h.element[ELEMENT_INDEX(i)] = ((value >> (i + 8)) & 1) == 1 ? 0xFFFF : 0; + vco.l.element[ELEMENT_INDEX(i)] = ((value >> i) & 1) == 1 ? 0xFFFF : 0; + } + break; + case 1: + for (int i = 0; i < 8; i++) { + vcc.h.element[ELEMENT_INDEX(i)] = ((value >> (i + 8)) & 1) == 1 ? 0xFFFF : 0; + vcc.l.element[ELEMENT_INDEX(i)] = ((value >> i) & 1) == 1 ? 0xFFFF : 0; + } + break; + case 2: + case 3: + for (int i = 0; i < 8; i++) { + vce.element[ELEMENT_INDEX(i)] = ((value >> i) & 1) == 1 ? 0xFFFF : 0; + } + break; } - break; - case 1: - for (int i = 0; i < 8; i++) { - vcc.h.element[ELEMENT_INDEX(i)] = ((value >> (i + 8)) & 1) == 1 ? 0xFFFF : 0; - vcc.l.element[ELEMENT_INDEX(i)] = ((value >> i) & 1) == 1 ? 0xFFFF : 0; - } - break; - case 2: - case 3: - for (int i = 0; i < 8; i++) { - vce.element[ELEMENT_INDEX(i)] = ((value >> i) & 1) == 1 ? 0xFFFF : 0; - } - break; - } } void RSP::b(const Instruction instr, const bool cond) { - const u32 address = ((instr & 0xFFFF) << 2) + pc; - branch(address, cond); + const u32 address = ((instr & 0xFFFF) << 2) + pc; + branch(address, cond); } void RSP::blink(const Instruction instr, const bool cond) { - b(instr, cond); - gpr[31] = pc + 4; + b(instr, cond); + gpr[31] = pc + 4; } void RSP::lb(const Instruction instr) { - const u32 address = gpr[instr.base()] + (s16)instr; - gpr[instr.rt()] = (s32)(s8)ReadByte(address); + const u32 address = gpr[instr.base()] + (s16)instr; + gpr[instr.rt()] = (s32)(s8)ReadByte(address); } void RSP::lh(const Instruction instr) { - const u32 address = gpr[instr.base()] + (s16)instr; - gpr[instr.rt()] = (s32)(s16)ReadHalf(address); + const u32 address = gpr[instr.base()] + (s16)instr; + gpr[instr.rt()] = (s32)(s16)ReadHalf(address); } void RSP::lw(const Instruction instr) { - const u32 address = gpr[instr.base()] + (s16)instr; - gpr[instr.rt()] = ReadWord(address); + const u32 address = gpr[instr.base()] + (s16)instr; + gpr[instr.rt()] = ReadWord(address); } void RSP::lbu(const Instruction instr) { - const u32 address = gpr[instr.base()] + (s16)instr; - gpr[instr.rt()] = ReadByte(address); + const u32 address = gpr[instr.base()] + (s16)instr; + gpr[instr.rt()] = ReadByte(address); } void RSP::lhu(const Instruction instr) { - const u32 address = gpr[instr.base()] + (s16)instr; - gpr[instr.rt()] = ReadHalf(address); + const u32 address = gpr[instr.base()] + (s16)instr; + gpr[instr.rt()] = ReadHalf(address); } void RSP::lui(const Instruction instr) { - u32 imm = ((u16)instr) << 16; - gpr[instr.rt()] = imm; + u32 imm = ((u16)instr) << 16; + gpr[instr.rt()] = imm; } #define OFFSET(x) ((x) & 0x7F) void RSP::lqv(const Instruction instr) { - int e = instr.e1(); - u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - u32 end = ((addr & ~15) + 15); + int e = instr.e1(); + u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + u32 end = ((addr & ~15) + 15); - for (int i = 0; addr + i <= end && i + e < 16; i++) { - vpr[instr.vt()].byte[BYTE_INDEX(i + e)] = ReadByte(addr + i); - } + for (int i = 0; addr + i <= end && i + e < 16; i++) { + vpr[instr.vt()].byte[BYTE_INDEX(i + e)] = ReadByte(addr + i); + } } void RSP::lpv(const Instruction instr) { - const int e = instr.e1(); - u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); + const int e = instr.e1(); + u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); - const int addrOffset = addr & 7; - addr &= ~7; + const int addrOffset = addr & 7; + addr &= ~7; - for (int elem = 0; elem < 8; elem++) { - const int elemOffset = (16 - e + (elem + addrOffset)) & 0xF; + for (int elem = 0; elem < 8; elem++) { + const int elemOffset = (16 - e + (elem + addrOffset)) & 0xF; - u16 value = ReadByte(addr + elemOffset); - value <<= 8; - vpr[instr.vt()].element[ELEMENT_INDEX(elem)] = value; - } + u16 value = ReadByte(addr + elemOffset); + value <<= 8; + vpr[instr.vt()].element[ELEMENT_INDEX(elem)] = value; + } } void RSP::luv(const Instruction instr) { - u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); + u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); - const int e = instr.e1(); + const int e = instr.e1(); - const int addrOffset = addr & 7; - addr &= ~7; + const int addrOffset = addr & 7; + addr &= ~7; - for (int elem = 0; elem < 8; elem++) { - const int elemOffset = (16 - e + (elem + addrOffset)) & 0xF; + for (int elem = 0; elem < 8; elem++) { + const int elemOffset = (16 - e + (elem + addrOffset)) & 0xF; - u16 value = ReadByte(addr + elemOffset); - value <<= 7; - vpr[instr.vt()].element[ELEMENT_INDEX(elem)] = value; - } + u16 value = ReadByte(addr + elemOffset); + value <<= 7; + vpr[instr.vt()].element[ELEMENT_INDEX(elem)] = value; + } } void RSP::suv(const Instruction instr) { - u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); + u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); - const int start = instr.e1(); - const int end = start + 8; + const int start = instr.e1(); + const int end = start + 8; - for (int offset = start; offset < end; offset++) { - if ((offset & 15) < 8) { - WriteByte(addr++, vpr[instr.vt()].element[ELEMENT_INDEX(offset & 7)] >> 7); - } else { - WriteByte(addr++, vpr[instr.vt()].byte[BYTE_INDEX((offset & 7) << 1)]); + for (int offset = start; offset < end; offset++) { + if ((offset & 15) < 8) { + WriteByte(addr++, vpr[instr.vt()].element[ELEMENT_INDEX(offset & 7)] >> 7); + } else { + WriteByte(addr++, vpr[instr.vt()].byte[BYTE_INDEX((offset & 7) << 1)]); + } } - } } void RSP::ldv(const Instruction instr) { - const int e = instr.e1(); - u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); - const u32 end = e + 8 > 16 ? 16 : e + 8; + const int e = instr.e1(); + u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); + const u32 end = e + 8 > 16 ? 16 : e + 8; - for (int i = e; i < end; i++) { - vpr[instr.vt()].byte[BYTE_INDEX(i)] = ReadByte(addr); - addr++; - } + for (int i = e; i < end; i++) { + vpr[instr.vt()].byte[BYTE_INDEX(i)] = ReadByte(addr); + addr++; + } } void RSP::lsv(const Instruction instr) { - const u8 e = instr.e1(); - const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 1); - const u16 val = ReadHalf(addr); - vpr[instr.vt()].byte[BYTE_INDEX(e)] = val >> 8; - if (e < 15) { - vpr[instr.vt()].byte[BYTE_INDEX(e + 1)] = val; - } + const u8 e = instr.e1(); + const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 1); + const u16 val = ReadHalf(addr); + vpr[instr.vt()].byte[BYTE_INDEX(e)] = val >> 8; + if (e < 15) { + vpr[instr.vt()].byte[BYTE_INDEX(e + 1)] = val; + } } void RSP::lbv(const Instruction instr) { - const u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 0); - vpr[instr.vt()].byte[BYTE_INDEX(instr.e1())] = ReadByte(address); + const u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 0); + vpr[instr.vt()].byte[BYTE_INDEX(instr.e1())] = ReadByte(address); } void RSP::llv(const Instruction instr) { - const int e = instr.e1(); - const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 2); + const int e = instr.e1(); + const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 2); - for (int i = 0; i < 4; i++) { - const int elem = i + e; - if (elem > 15) { - break; + for (int i = 0; i < 4; i++) { + const int elem = i + e; + if (elem > 15) { + break; + } + + vpr[instr.vt()].byte[BYTE_INDEX(elem)] = ReadByte(addr + i); } - - vpr[instr.vt()].byte[BYTE_INDEX(elem)] = ReadByte(addr + i); - } } void RSP::j(const Instruction instr) { - const u32 target = (instr & 0x3ffffff) << 2; - nextPC = target; + const u32 target = (instr & 0x3ffffff) << 2; + nextPC = target; } void RSP::jal(const Instruction instr) { - j(instr); - gpr[31] = pc + 4; + j(instr); + gpr[31] = pc + 4; } void RSP::jr(const Instruction instr) { nextPC = gpr[instr.rs()]; } void RSP::jalr(const Instruction instr) { - jr(instr); - gpr[instr.rd()] = pc + 4; + jr(instr); + gpr[instr.rd()] = pc + 4; } void RSP::nor(const Instruction instr) { gpr[instr.rd()] = ~(gpr[instr.rt()] | gpr[instr.rs()]); } void RSP::ori(const Instruction instr) { - const s32 op1 = gpr[instr.rs()]; - const u32 op2 = instr & 0xffff; - const s32 result = op1 | op2; - gpr[instr.rt()] = result; + const s32 op1 = gpr[instr.rs()]; + const u32 op2 = instr & 0xffff; + const s32 result = op1 | op2; + gpr[instr.rt()] = result; } void RSP::xori(const Instruction instr) { - const s32 op1 = gpr[instr.rs()]; - const u32 op2 = instr & 0xffff; - const s32 result = op1 ^ op2; - gpr[instr.rt()] = result; + const s32 op1 = gpr[instr.rs()]; + const u32 op2 = instr & 0xffff; + const s32 result = op1 ^ op2; + gpr[instr.rt()] = result; } void RSP::or_(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rt()] | gpr[instr.rs()]; } @@ -409,311 +409,311 @@ void RSP::or_(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rt()] | gpr void RSP::xor_(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rt()] ^ gpr[instr.rs()]; } void RSP::sb(const Instruction instr) { - const u32 address = gpr[instr.base()] + (s16)instr; - WriteByte(address, gpr[instr.rt()]); + const u32 address = gpr[instr.base()] + (s16)instr; + WriteByte(address, gpr[instr.rt()]); } void RSP::sh(const Instruction instr) { - const s16 imm = s16(instr); - const u32 address = gpr[instr.rs()] + imm; - WriteHalf(address, gpr[instr.rt()]); + const s16 imm = s16(instr); + const u32 address = gpr[instr.rs()] + imm; + WriteHalf(address, gpr[instr.rt()]); } void RSP::sw(const Instruction instr) { - const u32 address = gpr[instr.base()] + (s16)instr; - WriteWord(address, gpr[instr.rt()]); + const u32 address = gpr[instr.base()] + (s16)instr; + WriteWord(address, gpr[instr.rt()]); } void RSP::swv(const Instruction instr) { - u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - int base = address & 7; - address &= ~7; + u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + int base = address & 7; + address &= ~7; - for (int i = instr.e1(); i < instr.e1() + 16; i++) { - WriteByte(address + (base & 15), vpr[instr.vt()].byte[BYTE_INDEX(i & 15)]); - base++; - } + for (int i = instr.e1(); i < instr.e1() + 16; i++) { + WriteByte(address + (base & 15), vpr[instr.vt()].byte[BYTE_INDEX(i & 15)]); + base++; + } } void RSP::sub(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rs()] - gpr[instr.rt()]; } void RSP::sqv(const Instruction instr) { - const int e = instr.e1(); - const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const u32 end = ((addr & ~15) + 15); + const int e = instr.e1(); + const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + const u32 end = ((addr & ~15) + 15); - for (int i = 0; addr + i <= end; i++) { - WriteByte(addr + i, vpr[instr.vt()].byte[BYTE_INDEX((i + e) & 15)]); - } + for (int i = 0; addr + i <= end; i++) { + WriteByte(addr + i, vpr[instr.vt()].byte[BYTE_INDEX((i + e) & 15)]); + } } void RSP::spv(const Instruction instr) { - const int e = instr.e1(); - u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); + const int e = instr.e1(); + u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); - const int start = e; - const int end = start + 8; + const int start = e; + const int end = start + 8; - for (int offset = start; offset < end; offset++) { - if ((offset & 15) < 8) { - WriteByte(addr++, vpr[instr.vt()].byte[BYTE_INDEX((offset & 7) << 1)]); - } else { - WriteByte(addr++, vpr[instr.vt()].element[ELEMENT_INDEX(offset & 7)] >> 7); + for (int offset = start; offset < end; offset++) { + if ((offset & 15) < 8) { + WriteByte(addr++, vpr[instr.vt()].byte[BYTE_INDEX((offset & 7) << 1)]); + } else { + WriteByte(addr++, vpr[instr.vt()].element[ELEMENT_INDEX(offset & 7)] >> 7); + } } - } } void RSP::srv(const Instruction instr) { - u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const int start = instr.e1(); - const int end = start + (address & 15); - const int base = 16 - (address & 15); - address &= ~15; - for (int i = start; i < end; i++) { - WriteByte(address++, vpr[instr.vt()].byte[BYTE_INDEX((i + base) & 0xF)]); - } + u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + const int start = instr.e1(); + const int end = start + (address & 15); + const int base = 16 - (address & 15); + address &= ~15; + for (int i = start; i < end; i++) { + WriteByte(address++, vpr[instr.vt()].byte[BYTE_INDEX((i + base) & 0xF)]); + } } void RSP::shv(const Instruction instr) { - u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const u32 in_addr_offset = address & 0x7; - address &= ~0x7; + const u32 in_addr_offset = address & 0x7; + address &= ~0x7; - const int e = instr.e1(); + const int e = instr.e1(); - for (int i = 0; i < 8; i++) { - const int byte_index = (i * 2) + e; - u16 val = vpr[instr.vt()].byte[BYTE_INDEX(byte_index & 15)] << 1; - val |= vpr[instr.vt()].byte[BYTE_INDEX((byte_index + 1) & 15)] >> 7; - u8 b = val & 0xFF; + for (int i = 0; i < 8; i++) { + const int byte_index = (i * 2) + e; + u16 val = vpr[instr.vt()].byte[BYTE_INDEX(byte_index & 15)] << 1; + val |= vpr[instr.vt()].byte[BYTE_INDEX((byte_index + 1) & 15)] >> 7; + u8 b = val & 0xFF; - const int ofs = in_addr_offset + (i * 2); - WriteByte(address + (ofs & 0xF), b); - } + const int ofs = in_addr_offset + (i * 2); + WriteByte(address + (ofs & 0xF), b); + } } void RSP::lhv(const Instruction instr) { - u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const u32 in_addr_offset = address & 0x7; - address &= ~0x7; + const u32 in_addr_offset = address & 0x7; + address &= ~0x7; - const int e = instr.e1(); + const int e = instr.e1(); - for (int i = 0; i < 8; i++) { - const int ofs = ((16 - e) + (i * 2) + in_addr_offset) & 0xF; - u16 val = ReadByte(address + ofs); - val <<= 7; - vpr[instr.vt()].element[ELEMENT_INDEX(i)] = val; - } + for (int i = 0; i < 8; i++) { + const int ofs = ((16 - e) + (i * 2) + in_addr_offset) & 0xF; + u16 val = ReadByte(address + ofs); + val <<= 7; + vpr[instr.vt()].element[ELEMENT_INDEX(i)] = val; + } } void RSP::lfv(const Instruction instr) { - VPR &vt = vpr[instr.vt()]; - const int start = instr.e1(); - u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const u32 base = (address & 7) - start; - address &= ~7; + VPR &vt = vpr[instr.vt()]; + const int start = instr.e1(); + u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + const u32 base = (address & 7) - start; + address &= ~7; - const int end = std::min(start + 8, 16); + const int end = std::min(start + 8, 16); - // TODO: should be possible to do with one loop - VPR tmp{}; - for (u32 offset = 0; offset < 4; offset++) { - tmp.element[ELEMENT_INDEX(offset + 0)] = ReadByte(address + (base + offset * 4 + 0 & 15)) << 7; - tmp.element[ELEMENT_INDEX(offset + 4)] = ReadByte(address + (base + offset * 4 + 8 & 15)) << 7; - } + // TODO: should be possible to do with one loop + VPR tmp{}; + for (u32 offset = 0; offset < 4; offset++) { + tmp.element[ELEMENT_INDEX(offset + 0)] = ReadByte(address + (base + offset * 4 + 0 & 15)) << 7; + tmp.element[ELEMENT_INDEX(offset + 4)] = ReadByte(address + (base + offset * 4 + 8 & 15)) << 7; + } - for (u32 offset = start; offset < end; offset++) { - vt.byte[BYTE_INDEX(offset)] = tmp.byte[BYTE_INDEX(offset)]; - } + for (u32 offset = start; offset < end; offset++) { + vt.byte[BYTE_INDEX(offset)] = tmp.byte[BYTE_INDEX(offset)]; + } } void RSP::lrv(const Instruction instr) { - u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const int e = instr.e1(); - const int start = 16 - ((address & 15) - e); - address &= ~15; + u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + const int e = instr.e1(); + const int start = 16 - ((address & 15) - e); + address &= ~15; - for (int i = start; i < 16; i++) { - vpr[instr.vt()].byte[BYTE_INDEX(i & 0xF)] = ReadByte(address++); - } + for (int i = start; i < 16; i++) { + vpr[instr.vt()].byte[BYTE_INDEX(i & 0xF)] = ReadByte(address++); + } } void RSP::sfv(const Instruction instr) { - const VPR &vt = vpr[instr.vt()]; - u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const int base = address & 7; - address &= ~7; - const int e = instr.e1(); + const VPR &vt = vpr[instr.vt()]; + u32 address = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + const int base = address & 7; + address &= ~7; + const int e = instr.e1(); - u8 values[4] = {0, 0, 0, 0}; + u8 values[4] = {0, 0, 0, 0}; - switch (e) { - case 0: - case 15: - values[0] = vt.element[ELEMENT_INDEX(0)] >> 7; - values[1] = vt.element[ELEMENT_INDEX(1)] >> 7; - values[2] = vt.element[ELEMENT_INDEX(2)] >> 7; - values[3] = vt.element[ELEMENT_INDEX(3)] >> 7; - break; - case 1: - values[0] = vt.element[ELEMENT_INDEX(6)] >> 7; - values[1] = vt.element[ELEMENT_INDEX(7)] >> 7; - values[2] = vt.element[ELEMENT_INDEX(4)] >> 7; - values[3] = vt.element[ELEMENT_INDEX(5)] >> 7; - break; - case 4: - values[0] = vt.element[ELEMENT_INDEX(1)] >> 7; - values[1] = vt.element[ELEMENT_INDEX(2)] >> 7; - values[2] = vt.element[ELEMENT_INDEX(3)] >> 7; - values[3] = vt.element[ELEMENT_INDEX(0)] >> 7; - break; - case 5: - values[0] = vt.element[ELEMENT_INDEX(7)] >> 7; - values[1] = vt.element[ELEMENT_INDEX(4)] >> 7; - values[2] = vt.element[ELEMENT_INDEX(5)] >> 7; - values[3] = vt.element[ELEMENT_INDEX(6)] >> 7; - break; - case 8: - values[0] = vt.element[ELEMENT_INDEX(4)] >> 7; - values[1] = vt.element[ELEMENT_INDEX(5)] >> 7; - values[2] = vt.element[ELEMENT_INDEX(6)] >> 7; - values[3] = vt.element[ELEMENT_INDEX(7)] >> 7; - break; - case 11: - values[0] = vt.element[ELEMENT_INDEX(3)] >> 7; - values[1] = vt.element[ELEMENT_INDEX(0)] >> 7; - values[2] = vt.element[ELEMENT_INDEX(1)] >> 7; - values[3] = vt.element[ELEMENT_INDEX(2)] >> 7; - break; - case 12: - values[0] = vt.element[ELEMENT_INDEX(5)] >> 7; - values[1] = vt.element[ELEMENT_INDEX(6)] >> 7; - values[2] = vt.element[ELEMENT_INDEX(7)] >> 7; - values[3] = vt.element[ELEMENT_INDEX(4)] >> 7; - break; - default: - break; - } + switch (e) { + case 0: + case 15: + values[0] = vt.element[ELEMENT_INDEX(0)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(1)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(2)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(3)] >> 7; + break; + case 1: + values[0] = vt.element[ELEMENT_INDEX(6)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(7)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(4)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(5)] >> 7; + break; + case 4: + values[0] = vt.element[ELEMENT_INDEX(1)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(2)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(3)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(0)] >> 7; + break; + case 5: + values[0] = vt.element[ELEMENT_INDEX(7)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(4)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(5)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(6)] >> 7; + break; + case 8: + values[0] = vt.element[ELEMENT_INDEX(4)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(5)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(6)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(7)] >> 7; + break; + case 11: + values[0] = vt.element[ELEMENT_INDEX(3)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(0)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(1)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(2)] >> 7; + break; + case 12: + values[0] = vt.element[ELEMENT_INDEX(5)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(6)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(7)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(4)] >> 7; + break; + default: + break; + } - for (int i = 0; i < 4; i++) { - WriteByte(address + ((base + (i << 2)) & 15), values[i]); - } + for (int i = 0; i < 4; i++) { + WriteByte(address + ((base + (i << 2)) & 15), values[i]); + } } void RSP::sbv(const Instruction instr) { - const int e = instr.e1(); - const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 0); + const int e = instr.e1(); + const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 0); - WriteByte(addr, vpr[instr.vt()].byte[BYTE_INDEX(e & 0xF)]); + WriteByte(addr, vpr[instr.vt()].byte[BYTE_INDEX(e & 0xF)]); } void RSP::sdv(const Instruction instr) { - const int e = instr.e1(); - const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); + const int e = instr.e1(); + const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 3); - for (int i = 0; i < 8; i++) { - WriteByte(addr + i, vpr[instr.vt()].byte[BYTE_INDEX((i + e) & 0xF)]); - } + for (int i = 0; i < 8; i++) { + WriteByte(addr + i, vpr[instr.vt()].byte[BYTE_INDEX((i + e) & 0xF)]); + } } void RSP::ssv(const Instruction instr) { - const int e = instr.e1(); - const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 1); + const int e = instr.e1(); + const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 1); - const u8 hi = vpr[instr.vt()].byte[BYTE_INDEX(e & 15)]; - const u8 lo = vpr[instr.vt()].byte[BYTE_INDEX((e + 1) & 15)]; - const u16 val = (u16)hi << 8 | lo; + const u8 hi = vpr[instr.vt()].byte[BYTE_INDEX(e & 15)]; + const u8 lo = vpr[instr.vt()].byte[BYTE_INDEX((e + 1) & 15)]; + const u16 val = (u16)hi << 8 | lo; - WriteHalf(addr, val); + WriteHalf(addr, val); } void RSP::slv(const Instruction instr) { - const int e = instr.e1(); - const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 2); + const int e = instr.e1(); + const u32 addr = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 2); - for (int i = 0; i < 4; i++) { - WriteByte(addr + i, vpr[instr.vt()].byte[BYTE_INDEX((i + e) & 0xF)]); - } + for (int i = 0; i < 4; i++) { + WriteByte(addr + i, vpr[instr.vt()].byte[BYTE_INDEX((i + e) & 0xF)]); + } } void RSP::stv(const Instruction instr) { - u32 base = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - const u32 addrOffset = base & 0x7; - base &= ~0x7; + u32 base = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + const u32 addrOffset = base & 0x7; + base &= ~0x7; - const u8 e = instr.e1() >> 1; + const u8 e = instr.e1() >> 1; - for (int i = 0; i < 8; i++) { - const u32 address = base; - const u32 offset = (i << 1) + addrOffset; + for (int i = 0; i < 8; i++) { + const u32 address = base; + const u32 offset = (i << 1) + addrOffset; - const int reg = (instr.vt() & 0x18) | ((i + e) & 0x7); + const int reg = (instr.vt() & 0x18) | ((i + e) & 0x7); - const u16 val = vpr[reg].element[ELEMENT_INDEX(i & 0x7)]; - const u16 hi = (val >> 8) & 0xFF; - const u16 lo = (val >> 0) & 0xFF; + const u16 val = vpr[reg].element[ELEMENT_INDEX(i & 0x7)]; + const u16 hi = (val >> 8) & 0xFF; + const u16 lo = (val >> 0) & 0xFF; - WriteByte(address + ((offset + 0) & 0xF), hi); - WriteByte(address + ((offset + 1) & 0xF), lo); - } + WriteByte(address + ((offset + 0) & 0xF), hi); + WriteByte(address + ((offset + 1) & 0xF), lo); + } } void RSP::ltv(const Instruction instr) { - u32 base = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); - base &= ~0x7; + u32 base = gpr[instr.base()] + SignExt7bit(OFFSET(instr), 4); + base &= ~0x7; - const u8 e = instr.e1(); + const u8 e = instr.e1(); - for (int i = 0; i < 8; i++) { - const u32 address = base; - const u32 offset = (i << 1) + e + (base & 8); + for (int i = 0; i < 8; i++) { + const u32 address = base; + const u32 offset = (i << 1) + e + (base & 8); - const u16 hi = ReadByte(address + (offset & 0xF)); - const u16 lo = ReadByte(address + ((offset + 1) & 0xF)); + const u16 hi = ReadByte(address + (offset & 0xF)); + const u16 lo = ReadByte(address + ((offset + 1) & 0xF)); - const int reg = (instr.vt() & 0x18) | ((i + (e >> 1)) & 0x7); + const int reg = (instr.vt() & 0x18) | ((i + (e >> 1)) & 0x7); - vpr[reg].element[ELEMENT_INDEX(i & 0x7)] = (hi << 8) | lo; - } + vpr[reg].element[ELEMENT_INDEX(i & 0x7)] = (hi << 8) | lo; + } } void RSP::sllv(const Instruction instr) { - const u8 sa = (gpr[instr.rs()]) & 0x1F; - const u32 rt = gpr[instr.rt()]; - const u32 result = rt << sa; - gpr[instr.rd()] = result; + const u8 sa = (gpr[instr.rs()]) & 0x1F; + const u32 rt = gpr[instr.rt()]; + const u32 result = rt << sa; + gpr[instr.rd()] = result; } void RSP::srlv(const Instruction instr) { - const u8 sa = (gpr[instr.rs()]) & 0x1F; - const u32 rt = gpr[instr.rt()]; - const u32 result = rt >> sa; - gpr[instr.rd()] = result; + const u8 sa = (gpr[instr.rs()]) & 0x1F; + const u32 rt = gpr[instr.rt()]; + const u32 result = rt >> sa; + gpr[instr.rd()] = result; } void RSP::srav(const Instruction instr) { - const u8 sa = gpr[instr.rs()] & 0x1F; - const s32 rt = gpr[instr.rt()]; - const s32 result = rt >> sa; - gpr[instr.rd()] = result; + const u8 sa = gpr[instr.rs()] & 0x1F; + const s32 rt = gpr[instr.rt()]; + const s32 result = rt >> sa; + gpr[instr.rd()] = result; } void RSP::sll(const Instruction instr) { - const u8 sa = (instr >> 6) & 0x1f; - gpr[instr.rd()] = (u32)gpr[instr.rt()] << sa; + const u8 sa = (instr >> 6) & 0x1f; + gpr[instr.rd()] = (u32)gpr[instr.rt()] << sa; } void RSP::srl(const Instruction instr) { - const u8 sa = (instr >> 6) & 0x1f; - gpr[instr.rd()] = (u32)gpr[instr.rt()] >> sa; + const u8 sa = (instr >> 6) & 0x1f; + gpr[instr.rd()] = (u32)gpr[instr.rt()] >> sa; } void RSP::sra(const Instruction instr) { - const u8 sa = (instr >> 6) & 0x1f; - gpr[instr.rd()] = gpr[instr.rt()] >> sa; + const u8 sa = (instr >> 6) & 0x1f; + gpr[instr.rd()] = gpr[instr.rt()] >> sa; } void RSP::slt(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rs()] < gpr[instr.rt()]; } @@ -721,1105 +721,1105 @@ void RSP::slt(const Instruction instr) { gpr[instr.rd()] = gpr[instr.rs()] < gpr void RSP::sltu(const Instruction instr) { gpr[instr.rd()] = (u32)gpr[instr.rs()] < (u32)gpr[instr.rt()]; } void RSP::slti(const Instruction instr) { - const s32 imm = (s16)instr; - gpr[instr.rt()] = gpr[instr.rs()] < imm; + const s32 imm = (s16)instr; + gpr[instr.rt()] = gpr[instr.rs()] < imm; } void RSP::sltiu(const Instruction instr) { - const s32 imm = (s16)instr; - gpr[instr.rt()] = (u32)gpr[instr.rs()] < imm; + const s32 imm = (s16)instr; + gpr[instr.rt()] = (u32)gpr[instr.rs()] < imm; } FORCE_INLINE s16 signedClamp(const s64 val) { - if (val < -32768) - return -32768; - if (val > 32767) - return 32767; - return val; + if (val < -32768) + return -32768; + if (val > 32767) + return 32767; + return val; } FORCE_INLINE u16 unsignedClamp(const s64 val) { - if (val < 0) - return 0; - if (val > 32767) - return 65535; - return val; + if (val < 0) + return 0; + if (val > 32767) + return 65535; + return val; } #ifdef SIMD_SUPPORT void RSP::vabs(const Instruction instr) { - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], instr.e2()); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], instr.e2()); - const m128i isZero = _mm_cmpeq_epi16(vs.single, m128i{}); - const m128i isNeg = _mm_srai_epi16(vs.single, 15); - m128i temp = _mm_andnot_si128(isZero, vte.single); - temp = _mm_xor_si128(temp, isNeg); - acc.l.single = _mm_sub_epi16(temp, isNeg); - vd.single = _mm_subs_epi16(temp, isNeg); + const m128i isZero = _mm_cmpeq_epi16(vs.single, m128i{}); + const m128i isNeg = _mm_srai_epi16(vs.single, 15); + m128i temp = _mm_andnot_si128(isZero, vte.single); + temp = _mm_xor_si128(temp, isNeg); + acc.l.single = _mm_sub_epi16(temp, isNeg); + vd.single = _mm_subs_epi16(temp, isNeg); } #else void RSP::vabs(const Instruction instr) { - VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], instr.e2()); + VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], instr.e2()); - for (int i = 0; i < 8; i++) { - if (vs.selement[i] < 0) { - if (vte.element[i] == 0x8000) { - vd.element[i] = 0x7FFF; - acc.l.element[i] = 0x8000; - } else { - vd.element[i] = -vte.selement[i]; - acc.l.element[i] = -vte.selement[i]; - } - } else if (vs.element[i] == 0) { - vd.element[i] = 0; - acc.l.element[i] = 0; - } else { - vd.element[i] = vte.element[i]; - acc.l.element[i] = vte.element[i]; + for (int i = 0; i < 8; i++) { + if (vs.selement[i] < 0) { + if (vte.element[i] == 0x8000) { + vd.element[i] = 0x7FFF; + acc.l.element[i] = 0x8000; + } else { + vd.element[i] = -vte.selement[i]; + acc.l.element[i] = -vte.selement[i]; + } + } else if (vs.element[i] == 0) { + vd.element[i] = 0; + acc.l.element[i] = 0; + } else { + vd.element[i] = vte.element[i]; + acc.l.element[i] = vte.element[i]; + } } - } } #endif void RSP::vadd(const Instruction instr) { - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], instr.e2()); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], instr.e2()); - for (int i = 0; i < 8; i++) { - const s32 result = vs.selement[i] + vte.selement[i] + (vco.l.selement[i] != 0); - acc.l.element[i] = result; - vd.element[i] = (u16)signedClamp(result); - vco.l.element[i] = 0; - vco.h.element[i] = 0; - } + for (int i = 0; i < 8; i++) { + const s32 result = vs.selement[i] + vte.selement[i] + (vco.l.selement[i] != 0); + acc.l.element[i] = result; + vd.element[i] = (u16)signedClamp(result); + vco.l.element[i] = 0; + vco.h.element[i] = 0; + } } void RSP::vaddc(const Instruction instr) { - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], instr.e2()); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], instr.e2()); - for (int i = 0; i < 8; i++) { - const u32 result = vs.element[i] + vte.element[i]; - acc.l.element[i] = result; - vd.element[i] = result; - vco.l.element[i] = ((result >> 16) & 1) ? 0xffff : 0; - vco.h.element[i] = 0; - } + for (int i = 0; i < 8; i++) { + const u32 result = vs.element[i] + vte.element[i]; + acc.l.element[i] = result; + vd.element[i] = result; + vco.l.element[i] = ((result >> 16) & 1) ? 0xffff : 0; + vco.h.element[i] = 0; + } } void RSP::vch(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - s16 vsElem = vs.selement[i]; - s16 vteElem = vte.selement[i]; + for (int i = 0; i < 8; i++) { + s16 vsElem = vs.selement[i]; + s16 vteElem = vte.selement[i]; - vco.l.element[i] = ((vsElem ^ vteElem) < 0) ? 0xffff : 0; - if (vco.l.element[i]) { - const s16 result = vsElem + vteElem; + vco.l.element[i] = ((vsElem ^ vteElem) < 0) ? 0xffff : 0; + if (vco.l.element[i]) { + const s16 result = vsElem + vteElem; - acc.l.selement[i] = (result <= 0) ? -vteElem : vsElem; - vcc.l.element[i] = result <= 0 ? 0xffff : 0; - vcc.h.element[i] = vteElem < 0 ? 0xffff : 0; - vco.h.element[i] = (result != 0 && (vteElem != ~vsElem)) ? 0xffff : 0; - vce.element[i] = result == -1 ? 0xffff : 0; - } else { - const s16 result = vsElem - vteElem; - acc.l.element[i] = (result >= 0) ? vteElem : vsElem; - vcc.l.element[i] = vteElem < 0 ? 0xffff : 0; - vcc.h.element[i] = result >= 0 ? 0xffff : 0; - vco.h.element[i] = result != 0 ? 0xffff : 0; - vce.element[i] = 0; + acc.l.selement[i] = (result <= 0) ? -vteElem : vsElem; + vcc.l.element[i] = result <= 0 ? 0xffff : 0; + vcc.h.element[i] = vteElem < 0 ? 0xffff : 0; + vco.h.element[i] = (result != 0 && (vteElem != ~vsElem)) ? 0xffff : 0; + vce.element[i] = result == -1 ? 0xffff : 0; + } else { + const s16 result = vsElem - vteElem; + acc.l.element[i] = (result >= 0) ? vteElem : vsElem; + vcc.l.element[i] = vteElem < 0 ? 0xffff : 0; + vcc.h.element[i] = result >= 0 ? 0xffff : 0; + vco.h.element[i] = result != 0 ? 0xffff : 0; + vce.element[i] = 0; + } + + vd.element[i] = acc.l.element[i]; } - - vd.element[i] = acc.l.element[i]; - } } void RSP::vcr(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - u16 vsE = vs.element[i]; - const u16 vteE = vte.element[i]; + for (int i = 0; i < 8; i++) { + u16 vsE = vs.element[i]; + const u16 vteE = vte.element[i]; - const bool signDiff = (0x8000 & (vsE ^ vteE)) == 0x8000; + const bool signDiff = (0x8000 & (vsE ^ vteE)) == 0x8000; - u16 vtAbs = signDiff ? ~vteE : vteE; + u16 vtAbs = signDiff ? ~vteE : vteE; - bool gte = s16(vteE) <= s16(signDiff ? 0xffff : vsE); - bool lte = (((signDiff ? vsE : 0) + vteE) & 0x8000) == 0x8000; + bool gte = s16(vteE) <= s16(signDiff ? 0xffff : vsE); + bool lte = (((signDiff ? vsE : 0) + vteE) & 0x8000) == 0x8000; - const bool check = signDiff ? lte : gte; - const u16 result = check ? vtAbs : vsE; + const bool check = signDiff ? lte : gte; + const u16 result = check ? vtAbs : vsE; - acc.l.element[i] = result; - vd.element[i] = result; + acc.l.element[i] = result; + vd.element[i] = result; - vcc.h.element[i] = gte ? 0xffff : 0; - vcc.l.element[i] = lte ? 0xffff : 0; + vcc.h.element[i] = gte ? 0xffff : 0; + vcc.l.element[i] = lte ? 0xffff : 0; - vco.l.element[i] = 0; - vco.h.element[i] = 0; - vce.element[i] = 0; - } + vco.l.element[i] = 0; + vco.h.element[i] = 0; + vce.element[i] = 0; + } } void RSP::vcl(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - u16 vs_element = vs.element[i]; - u16 vte_element = vte.element[i]; + for (int i = 0; i < 8; i++) { + u16 vs_element = vs.element[i]; + u16 vte_element = vte.element[i]; - if (vco.l.element[i]) { - if (!vco.h.element[i]) { - const u16 clamped_sum = vs_element + vte_element; - const bool overflow = (vs_element + vte_element) != clamped_sum; - if (vce.element[i]) { - vcc.l.element[i] = (!clamped_sum || !overflow) ? 0xffff : 0; + if (vco.l.element[i]) { + if (!vco.h.element[i]) { + const u16 clamped_sum = vs_element + vte_element; + const bool overflow = (vs_element + vte_element) != clamped_sum; + if (vce.element[i]) { + vcc.l.element[i] = (!clamped_sum || !overflow) ? 0xffff : 0; + } else { + vcc.l.element[i] = (!clamped_sum && !overflow) ? 0xffff : 0; + } + } + acc.l.element[i] = vcc.l.element[i] ? -vte_element : vs_element; } else { - vcc.l.element[i] = (!clamped_sum && !overflow) ? 0xffff : 0; + if (!vco.h.element[i]) { + vcc.h.element[i] = ((s32)vs_element - (s32)vte_element >= 0) ? 0xffff : 0; + } + acc.l.element[i] = vcc.h.element[i] ? vte_element : vs_element; } - } - acc.l.element[i] = vcc.l.element[i] ? -vte_element : vs_element; - } else { - if (!vco.h.element[i]) { - vcc.h.element[i] = ((s32)vs_element - (s32)vte_element >= 0) ? 0xffff : 0; - } - acc.l.element[i] = vcc.h.element[i] ? vte_element : vs_element; - } - vco.l.element[i] = 0; - vco.h.element[i] = 0; - vce.element[i] = 0; - vd.element[i] = acc.l.element[i]; - } + vco.l.element[i] = 0; + vco.h.element[i] = 0; + vce.element[i] = 0; + vd.element[i] = acc.l.element[i]; + } } void RSP::vmov(const Instruction instr) { - const u8 e = instr.e2(), vs = instr.vs() & 7; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const u8 e = instr.e2(), vs = instr.vs() & 7; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - u8 se; - switch (e) { - case 0 ... 1: - se = (e & 0b000) | (vs & 0b111); - break; - case 2 ... 3: - se = (e & 0b001) | (vs & 0b110); - break; - case 4 ... 7: - se = (e & 0b011) | (vs & 0b100); - break; - case 8 ... 15: - se = (e & 0b111) | (vs & 0b000); - break; - default: - panic("VMOV: This should be unreachable!"); - } + u8 se; + switch (e) { + case 0 ... 1: + se = (e & 0b000) | (vs & 0b111); + break; + case 2 ... 3: + se = (e & 0b001) | (vs & 0b110); + break; + case 4 ... 7: + se = (e & 0b011) | (vs & 0b100); + break; + case 8 ... 15: + se = (e & 0b111) | (vs & 0b000); + break; + default: + ircolib::panic("VMOV: This should be unreachable!"); + } - const u8 de = vs & 7; + const u8 de = vs & 7; - vd.element[ELEMENT_INDEX(de)] = vte.element[ELEMENT_INDEX(se)]; + vd.element[ELEMENT_INDEX(de)] = vte.element[ELEMENT_INDEX(se)]; #ifdef SIMD_SUPPORT - acc.l.single = vte.single; + acc.l.single = vte.single; #else - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i]; + } #endif } FORCE_INLINE bool IsSignExtension(const s16 hi, const s16 lo) { - if (hi == 0) { - return (lo & 0x8000) == 0; - } - if (hi == -1) { - return (lo & 0x8000) == 0x8000; - } - return false; + if (hi == 0) { + return (lo & 0x8000) == 0; + } + if (hi == -1) { + return (lo & 0x8000) == 0x8000; + } + return false; } void RSP::vmulf(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const s16 op1 = vte.element[i]; - const s16 op2 = vs.element[i]; - const s32 prod = op1 * op2; + for (int i = 0; i < 8; i++) { + const s16 op1 = vte.element[i]; + const s16 op2 = vs.element[i]; + const s32 prod = op1 * op2; - s64 accum = prod; - accum = (accum * 2) + 0x8000; + s64 accum = prod; + accum = (accum * 2) + 0x8000; - SetACC(i, accum); + SetACC(i, accum); - const s16 result = signedClamp(accum >> 16); - vd.element[i] = result; - } + const s16 result = signedClamp(accum >> 16); + vd.element[i] = result; + } } void RSP::vmulq(const Instruction instr) { - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], instr.e2()); - VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], instr.e2()); + VPR &vd = vpr[instr.vd()]; - for (int i = 0; i < 8; i++) { - const bool neg = vte.selement[i] < 0 && vs.selement[i] >= 0 || vs.selement[i] < 0 && vte.selement[i] >= 0; - const s32 product = vs.selement[i] * vte.selement[i] + 31 * neg; + for (int i = 0; i < 8; i++) { + const bool neg = vte.selement[i] < 0 && vs.selement[i] >= 0 || vs.selement[i] < 0 && vte.selement[i] >= 0; + const s32 product = vs.selement[i] * vte.selement[i] + 31 * neg; - acc.h.element[i] = product >> 16; - acc.m.element[i] = product; - acc.l.element[i] = 0; - vd.element[i] = signedClamp(product >> 1) & ~15; - } + acc.h.element[i] = product >> 16; + acc.m.element[i] = product; + acc.l.element[i] = 0; + vd.element[i] = signedClamp(product >> 1) & ~15; + } } void RSP::vmulu(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const s16 op1 = vte.element[i]; - const s16 op2 = vs.element[i]; - const s32 prod = op1 * op2; + for (int i = 0; i < 8; i++) { + const s16 op1 = vte.element[i]; + const s16 op2 = vs.element[i]; + const s32 prod = op1 * op2; - s64 accum = prod; - accum = (accum * 2) + 0x8000; + s64 accum = prod; + accum = (accum * 2) + 0x8000; - SetACC(i, accum); + SetACC(i, accum); - const u16 result = unsignedClamp(accum >> 16); - vd.element[i] = result; - } + const u16 result = unsignedClamp(accum >> 16); + vd.element[i] = result; + } } void RSP::vmudl(const Instruction instr) { - const u8 e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const u64 op1 = vte.element[i]; - const u64 op2 = vs.element[i]; - const u64 prod = op1 * op2; - const u64 accum = prod >> 16; + const u8 e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); + for (int i = 0; i < 8; i++) { + const u64 op1 = vte.element[i]; + const u64 op2 = vs.element[i]; + const u64 prod = op1 * op2; + const u64 accum = prod >> 16; - SetACC(i, accum); + SetACC(i, accum); - u16 result; - if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { - result = acc.l.element[i]; - } else if (acc.h.selement[i] < 0) { - result = 0; - } else { - result = 0xffff; + u16 result; + if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { + result = acc.l.element[i]; + } else if (acc.h.selement[i] < 0) { + result = 0; + } else { + result = 0xffff; + } + + vd.element[i] = result; } - - vd.element[i] = result; - } } void RSP::vmudh(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const s32 prod = vs.selement[i] * vte.selement[i]; - const s16 result = signedClamp(prod); - const s64 accum = static_cast(prod) << 16; - SetACC(i, accum); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); + for (int i = 0; i < 8; i++) { + const s32 prod = vs.selement[i] * vte.selement[i]; + const s16 result = signedClamp(prod); + const s64 accum = static_cast(prod) << 16; + SetACC(i, accum); - vd.element[i] = result; - } + vd.element[i] = result; + } } void RSP::vmudm(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const s32 prod = vs.selement[i] * vte.element[i]; - const s64 accum = prod; - const s16 result = signedClamp(accum >> 16); - SetACC(i, accum); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); + for (int i = 0; i < 8; i++) { + const s32 prod = vs.selement[i] * vte.element[i]; + const s64 accum = prod; + const s16 result = signedClamp(accum >> 16); + SetACC(i, accum); - vd.element[i] = result; - } + vd.element[i] = result; + } } void RSP::vmudn(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const s16 op1 = vte.element[i]; - const u16 op2 = vs.element[i]; - const s32 prod = op1 * op2; - const s64 accum = prod; - SetACC(i, accum); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); + for (int i = 0; i < 8; i++) { + const s16 op1 = vte.element[i]; + const u16 op2 = vs.element[i]; + const s32 prod = op1 * op2; + const s64 accum = prod; + SetACC(i, accum); - u16 result; - if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { - result = acc.l.element[i]; - } else if (acc.h.selement[i] < 0) { - result = 0; - } else { - result = 0xffff; + u16 result; + if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { + result = acc.l.element[i]; + } else if (acc.h.selement[i] < 0) { + result = 0; + } else { + result = 0xffff; + } + + vd.element[i] = result; } - - vd.element[i] = result; - } } #ifdef SIMD_SUPPORT void RSP::vmadh(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); - m128i lo = _mm_mullo_epi16(vs.single, vte.single); - m128i hi = _mm_mulhi_epi16(vs.single, vte.single); - m128i omask = _mm_adds_epu16(acc.m.single, lo); - acc.m.single = _mm_add_epi16(acc.m.single, lo); - omask = _mm_cmpeq_epi16(acc.m.single, omask); - omask = _mm_cmpeq_epi16(omask, m128i{}); - hi = _mm_sub_epi16(hi, omask); - acc.h.single = _mm_add_epi16(acc.h.single, hi); - lo = _mm_unpacklo_epi16(acc.m.single, acc.h.single); - hi = _mm_unpackhi_epi16(acc.m.single, acc.h.single); - vd.single = _mm_packs_epi32(lo, hi); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); + m128i lo = _mm_mullo_epi16(vs.single, vte.single); + m128i hi = _mm_mulhi_epi16(vs.single, vte.single); + m128i omask = _mm_adds_epu16(acc.m.single, lo); + acc.m.single = _mm_add_epi16(acc.m.single, lo); + omask = _mm_cmpeq_epi16(acc.m.single, omask); + omask = _mm_cmpeq_epi16(omask, m128i{}); + hi = _mm_sub_epi16(hi, omask); + acc.h.single = _mm_add_epi16(acc.h.single, hi); + lo = _mm_unpacklo_epi16(acc.m.single, acc.h.single); + hi = _mm_unpackhi_epi16(acc.m.single, acc.h.single); + vd.single = _mm_packs_epi32(lo, hi); } #else void RSP::vmadh(const Instruction instr) { - int e = instr.e2(); - VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - s16 op1 = vte.element[i]; - s16 op2 = vs.element[i]; - s32 prod = op1 * op2; - u32 unsProd = prod; + int e = instr.e2(); + VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); + for (int i = 0; i < 8; i++) { + s16 op1 = vte.element[i]; + s16 op2 = vs.element[i]; + s32 prod = op1 * op2; + u32 unsProd = prod; - u64 accumDelta = (u64)unsProd << 16; - s64 accum = GetACC(i) + accumDelta; - SetACC(i, accum); - accum = GetACC(i); + u64 accumDelta = (u64)unsProd << 16; + s64 accum = GetACC(i) + accumDelta; + SetACC(i, accum); + accum = GetACC(i); - s16 result = signedClamp(accum >> 16); + s16 result = signedClamp(accum >> 16); - vd.element[i] = result; - } + vd.element[i] = result; + } } #endif void RSP::vmadl(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const u64 op1 = vte.element[i]; - const u64 op2 = vs.element[i]; - const u64 prod = op1 * op2; - const u64 accDelta = prod >> 16; - const u64 accum = GetACC(i) + accDelta; + for (int i = 0; i < 8; i++) { + const u64 op1 = vte.element[i]; + const u64 op2 = vs.element[i]; + const u64 prod = op1 * op2; + const u64 accDelta = prod >> 16; + const u64 accum = GetACC(i) + accDelta; - SetACC(i, accum); + SetACC(i, accum); - u16 result; - if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { - result = acc.l.element[i]; - } else if (acc.h.selement[i] < 0) { - result = 0; - } else { - result = 0xffff; + u16 result; + if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { + result = acc.l.element[i]; + } else if (acc.h.selement[i] < 0) { + result = 0; + } else { + result = 0xffff; + } + + vd.element[i] = result; } - - vd.element[i] = result; - } } #ifdef SIMD_SUPPORT void RSP::vmadm(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], e); - m128i lo = _mm_mullo_epi16(vs.single, vte.single); - m128i hi = _mm_mulhi_epu16(vs.single, vte.single); - const m128i sign = _mm_srai_epi16(vs.single, 15); - const m128i vta = _mm_and_si128(vte.single, sign); - hi = _mm_sub_epi16(hi, vta); - m128i omask = _mm_adds_epu16(acc.l.single, lo); - acc.l.single = _mm_add_epi16(acc.l.single, lo); - omask = _mm_cmpeq_epi16(acc.l.single, omask); - omask = _mm_cmpeq_epi16(omask, m128i{}); - hi = _mm_sub_epi16(hi, omask); - omask = _mm_adds_epu16(acc.m.single, hi); - acc.m.single = _mm_add_epi16(acc.m.single, hi); - omask = _mm_cmpeq_epi16(acc.m.single, omask); - omask = _mm_cmpeq_epi16(omask, m128i{}); - hi = _mm_srai_epi16(hi, 15); - acc.h.single = _mm_add_epi16(acc.h.single, hi); - acc.h.single = _mm_sub_epi16(acc.h.single, omask); - lo = _mm_unpacklo_epi16(acc.m.single, acc.h.single); - hi = _mm_unpackhi_epi16(acc.m.single, acc.h.single); - VPR &vd = vpr[instr.vd()]; - vd.single = _mm_packs_epi32(lo, hi); + m128i lo = _mm_mullo_epi16(vs.single, vte.single); + m128i hi = _mm_mulhi_epu16(vs.single, vte.single); + const m128i sign = _mm_srai_epi16(vs.single, 15); + const m128i vta = _mm_and_si128(vte.single, sign); + hi = _mm_sub_epi16(hi, vta); + m128i omask = _mm_adds_epu16(acc.l.single, lo); + acc.l.single = _mm_add_epi16(acc.l.single, lo); + omask = _mm_cmpeq_epi16(acc.l.single, omask); + omask = _mm_cmpeq_epi16(omask, m128i{}); + hi = _mm_sub_epi16(hi, omask); + omask = _mm_adds_epu16(acc.m.single, hi); + acc.m.single = _mm_add_epi16(acc.m.single, hi); + omask = _mm_cmpeq_epi16(acc.m.single, omask); + omask = _mm_cmpeq_epi16(omask, m128i{}); + hi = _mm_srai_epi16(hi, 15); + acc.h.single = _mm_add_epi16(acc.h.single, hi); + acc.h.single = _mm_sub_epi16(acc.h.single, omask); + lo = _mm_unpacklo_epi16(acc.m.single, acc.h.single); + hi = _mm_unpackhi_epi16(acc.m.single, acc.h.single); + VPR &vd = vpr[instr.vd()]; + vd.single = _mm_packs_epi32(lo, hi); } void RSP::vmadn(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], e); - const m128i lo = _mm_mullo_epi16(vs.single, vte.single); - m128i hi = _mm_mulhi_epu16(vs.single, vte.single); - const m128i sign = _mm_srai_epi16(vte.single, 15); - const m128i vsa = _mm_and_si128(vs.single, sign); - hi = _mm_sub_epi16(hi, vsa); - m128i omask = _mm_adds_epu16(acc.l.single, lo); - acc.l.single = _mm_add_epi16(acc.l.single, lo); - omask = _mm_cmpeq_epi16(acc.l.single, omask); - omask = _mm_cmpeq_epi16(omask, m128i{}); - hi = _mm_sub_epi16(hi, omask); - omask = _mm_adds_epu16(acc.m.single, hi); - acc.m.single = _mm_add_epi16(acc.m.single, hi); - omask = _mm_cmpeq_epi16(acc.m.single, omask); - omask = _mm_cmpeq_epi16(omask, m128i{}); - hi = _mm_srai_epi16(hi, 15); - acc.h.single = _mm_add_epi16(acc.h.single, hi); - acc.h.single = _mm_sub_epi16(acc.h.single, omask); - const m128i nhi = _mm_srai_epi16(acc.h.single, 15); - const m128i nmd = _mm_srai_epi16(acc.m.single, 15); - const m128i shi = _mm_cmpeq_epi16(nhi, acc.h.single); - const m128i smd = _mm_cmpeq_epi16(nhi, nmd); - const m128i cmask = _mm_and_si128(smd, shi); - const m128i cval = _mm_cmpeq_epi16(nhi, m128i{}); - VPR &vd = vpr[instr.vd()]; - vd.single = _mm_blendv_epi8(cval, acc.l.single, cmask); + const m128i lo = _mm_mullo_epi16(vs.single, vte.single); + m128i hi = _mm_mulhi_epu16(vs.single, vte.single); + const m128i sign = _mm_srai_epi16(vte.single, 15); + const m128i vsa = _mm_and_si128(vs.single, sign); + hi = _mm_sub_epi16(hi, vsa); + m128i omask = _mm_adds_epu16(acc.l.single, lo); + acc.l.single = _mm_add_epi16(acc.l.single, lo); + omask = _mm_cmpeq_epi16(acc.l.single, omask); + omask = _mm_cmpeq_epi16(omask, m128i{}); + hi = _mm_sub_epi16(hi, omask); + omask = _mm_adds_epu16(acc.m.single, hi); + acc.m.single = _mm_add_epi16(acc.m.single, hi); + omask = _mm_cmpeq_epi16(acc.m.single, omask); + omask = _mm_cmpeq_epi16(omask, m128i{}); + hi = _mm_srai_epi16(hi, 15); + acc.h.single = _mm_add_epi16(acc.h.single, hi); + acc.h.single = _mm_sub_epi16(acc.h.single, omask); + const m128i nhi = _mm_srai_epi16(acc.h.single, 15); + const m128i nmd = _mm_srai_epi16(acc.m.single, 15); + const m128i shi = _mm_cmpeq_epi16(nhi, acc.h.single); + const m128i smd = _mm_cmpeq_epi16(nhi, nmd); + const m128i cmask = _mm_and_si128(smd, shi); + const m128i cval = _mm_cmpeq_epi16(nhi, m128i{}); + VPR &vd = vpr[instr.vd()]; + vd.single = _mm_blendv_epi8(cval, acc.l.single, cmask); } #else void RSP::vmadm(const Instruction instr) { - int e = instr.e2(); - VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + int e = instr.e2(); + VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - s32 prod = vs.selement[i] * vte.element[i]; - s64 accum = GetACC(i); - accum += prod; - SetACC(i, accum); - accum = GetACC(i); + for (int i = 0; i < 8; i++) { + s32 prod = vs.selement[i] * vte.element[i]; + s64 accum = GetACC(i); + accum += prod; + SetACC(i, accum); + accum = GetACC(i); - s16 result = signedClamp(accum >> 16); + s16 result = signedClamp(accum >> 16); - vd.element[i] = result; - } + vd.element[i] = result; + } } void RSP::vmadn(const Instruction instr) { - int e = instr.e2(); - VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + int e = instr.e2(); + VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - s32 prod = vs.element[i] * vte.selement[i]; - s64 accum = GetACC(i) + prod; + for (int i = 0; i < 8; i++) { + s32 prod = vs.element[i] * vte.selement[i]; + s64 accum = GetACC(i) + prod; - SetACC(i, accum); + SetACC(i, accum); - u16 result; - if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { - result = acc.l.element[i]; - } else if (acc.h.selement[i] < 0) { - result = 0; - } else { - result = 0xffff; + u16 result; + if (IsSignExtension(acc.h.selement[i], acc.m.selement[i])) { + result = acc.l.element[i]; + } else if (acc.h.selement[i] < 0) { + result = 0; + } else { + result = 0xffff; + } + + vd.element[i] = result; } - - vd.element[i] = result; - } } #endif void RSP::vmacf(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], instr.e2()); + VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], instr.e2()); - for (int i = 0; i < 8; i++) { - const s16 op1 = vte.element[i]; - const s16 op2 = vs.element[i]; - const s32 prod = op1 * op2; + for (int i = 0; i < 8; i++) { + const s16 op1 = vte.element[i]; + const s16 op2 = vs.element[i]; + const s32 prod = op1 * op2; - const s64 accDelta = static_cast(prod) * 2; - s64 accum = GetACC(i) + accDelta; - SetACC(i, accum); - accum = GetACC(i); + const s64 accDelta = static_cast(prod) * 2; + s64 accum = GetACC(i) + accDelta; + SetACC(i, accum); + accum = GetACC(i); - const s16 result = signedClamp(accum >> 16); - vd.element[i] = result; - } + const s16 result = signedClamp(accum >> 16); + vd.element[i] = result; + } } void RSP::vmacu(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], instr.e2()); + VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], instr.e2()); - for (int i = 0; i < 8; i++) { - const s16 op1 = vte.element[i]; - const s16 op2 = vs.element[i]; - const s32 prod = op1 * op2; - const s64 accDelta = static_cast(prod) * 2; - s64 accum = GetACC(i) + accDelta; - SetACC(i, accum); - accum = GetACC(i); + for (int i = 0; i < 8; i++) { + const s16 op1 = vte.element[i]; + const s16 op2 = vs.element[i]; + const s32 prod = op1 * op2; + const s64 accDelta = static_cast(prod) * 2; + s64 accum = GetACC(i) + accDelta; + SetACC(i, accum); + accum = GetACC(i); - const u16 result = unsignedClamp(accum >> 16); - vd.element[i] = result; - } + const u16 result = unsignedClamp(accum >> 16); + vd.element[i] = result; + } } void RSP::vmacq(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; + VPR &vd = vpr[instr.vd()]; - for (int i = 0; i < 8; i++) { - s32 product = acc.h.element[i] << 16 | acc.m.element[i]; - if (product < 0 && !(product & 1 << 5)) { - product += 32; - } else if (product >= 32 && !(product & 1 << 5)) { - product -= 32; + for (int i = 0; i < 8; i++) { + s32 product = acc.h.element[i] << 16 | acc.m.element[i]; + if (product < 0 && !(product & 1 << 5)) { + product += 32; + } else if (product >= 32 && !(product & 1 << 5)) { + product -= 32; + } + acc.h.element[i] = product >> 16; + acc.m.element[i] = product & 0xFFFF; + + vd.element[i] = signedClamp(product >> 1) & ~15; } - acc.h.element[i] = product >> 16; - acc.m.element[i] = product & 0xFFFF; - - vd.element[i] = signedClamp(product >> 1) & ~15; - } } void RSP::veq(const Instruction instr) { - const int e = instr.e2(); - VPR &vd = vpr[instr.vd()]; - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - vcc.l.element[i] = vco.h.element[i] == 0 && vs.element[i] == vte.element[i] ? 0xffff : 0; - acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; - vd.element[i] = acc.l.element[i]; - vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; - } + for (int i = 0; i < 8; i++) { + vcc.l.element[i] = vco.h.element[i] == 0 && vs.element[i] == vte.element[i] ? 0xffff : 0; + acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; + vd.element[i] = acc.l.element[i]; + vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; + } } void RSP::vne(const Instruction instr) { - const int e = instr.e2(); - VPR &vd = vpr[instr.vd()]; - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - vcc.l.element[i] = vco.h.element[i] || vs.element[i] != vte.element[i] ? 0xffff : 0; - acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; - vd.element[i] = acc.l.element[i]; - vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; - } + for (int i = 0; i < 8; i++) { + vcc.l.element[i] = vco.h.element[i] || vs.element[i] != vte.element[i] ? 0xffff : 0; + acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; + vd.element[i] = acc.l.element[i]; + vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; + } } void RSP::vge(const Instruction instr) { - const int e = instr.e2(); - VPR &vd = vpr[instr.vd()]; - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const bool eql = vs.selement[i] == vte.selement[i]; - const bool neg = !(vco.h.element[i] && vco.l.element[i]) && eql; - vcc.l.element[i] = neg || vs.selement[i] > vte.selement[i] ? 0xffff : 0; - acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; - vd.element[i] = acc.l.element[i]; - vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; - } + for (int i = 0; i < 8; i++) { + const bool eql = vs.selement[i] == vte.selement[i]; + const bool neg = !(vco.h.element[i] && vco.l.element[i]) && eql; + vcc.l.element[i] = neg || vs.selement[i] > vte.selement[i] ? 0xffff : 0; + acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; + vd.element[i] = acc.l.element[i]; + vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; + } } void RSP::vlt(const Instruction instr) { - const int e = instr.e2(); - VPR &vd = vpr[instr.vd()]; - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const bool eql = vs.element[i] == vte.element[i]; - const bool neg = vco.h.element[i] && vco.l.element[i] && eql; - vcc.l.element[i] = neg || vs.selement[i] < vte.selement[i] ? 0xffff : 0; - acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; - vd.element[i] = acc.l.element[i]; - vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; - } + for (int i = 0; i < 8; i++) { + const bool eql = vs.element[i] == vte.element[i]; + const bool neg = vco.h.element[i] && vco.l.element[i] && eql; + vcc.l.element[i] = neg || vs.selement[i] < vte.selement[i] ? 0xffff : 0; + acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; + vd.element[i] = acc.l.element[i]; + vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; + } } FORCE_INLINE u32 rcp(const s32 sinput) { - const s32 mask = sinput >> 31; - s32 input = sinput ^ mask; - if (sinput > INT16_MIN) { - input -= mask; - } - if (input == 0) { - return 0x7FFFFFFF; - } - if (sinput == INT16_MIN) { - return 0xFFFF0000; - } + const s32 mask = sinput >> 31; + s32 input = sinput ^ mask; + if (sinput > INT16_MIN) { + input -= mask; + } + if (input == 0) { + return 0x7FFFFFFF; + } + if (sinput == INT16_MIN) { + return 0xFFFF0000; + } - const u32 shift = std::countl_zero(static_cast(input)); - const u64 dinput = static_cast(input); - const u32 index = (dinput << shift & 0x7FC00000) >> 22; + const u32 shift = std::countl_zero(static_cast(input)); + const u64 dinput = static_cast(input); + const u32 index = (dinput << shift & 0x7FC00000) >> 22; - s32 result = rcpRom[index]; - result = (0x10000 | result) << 14; - result = result >> (31 - shift) ^ mask; - return result; + s32 result = rcpRom[index]; + result = (0x10000 | result) << 14; + result = result >> (31 - shift) ^ mask; + return result; } FORCE_INLINE u32 rsq(u32 input) { - if (input == 0) { - return 0x7FFFFFFF; - } + if (input == 0) { + return 0x7FFFFFFF; + } - if (input == 0xFFFF8000) { - return 0xFFFF0000; - } + if (input == 0xFFFF8000) { + return 0xFFFF0000; + } - if (input > 0xFFFF8000) { - input--; - } + if (input > 0xFFFF8000) { + input--; + } - const s32 sinput = input; - const s32 mask = sinput >> 31; - input ^= mask; + const s32 sinput = input; + const s32 mask = sinput >> 31; + input ^= mask; - const int shift = std::countl_zero(input) + 1; + const int shift = std::countl_zero(input) + 1; - const int index = (((input << shift) >> 24) | ((shift & 1) << 8)); - const u32 rom = (((u32)rsqRom[index]) << 14); - const int r_shift = ((32 - shift) >> 1); - const u32 result = (0x40000000 | rom) >> r_shift; + const int index = (((input << shift) >> 24) | ((shift & 1) << 8)); + const u32 rom = (((u32)rsqRom[index]) << 14); + const int r_shift = ((32 - shift) >> 1); + const u32 result = (0x40000000 | rom) >> r_shift; - return result ^ mask; + return result ^ mask; } void RSP::vrcpl(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - const VPR &vt = vpr[instr.vt()]; - SetVTE(vpr[instr.vt()], instr.e2()); - const int e = instr.e2() & 7; - const int de = DE(instr) & 7; + VPR &vd = vpr[instr.vd()]; + const VPR &vt = vpr[instr.vt()]; + SetVTE(vpr[instr.vt()], instr.e2()); + const int e = instr.e2() & 7; + const int de = DE(instr) & 7; - s32 input; - if (divInLoaded) { - input = (s32(divIn) << 16) | vt.element[ELEMENT_INDEX(e)]; - } else { - input = vt.selement[ELEMENT_INDEX(e)]; - } + s32 input; + if (divInLoaded) { + input = (s32(divIn) << 16) | vt.element[ELEMENT_INDEX(e)]; + } else { + input = vt.selement[ELEMENT_INDEX(e)]; + } - const s32 result = rcp(input); - divOut = result >> 16; - divIn = 0; - divInLoaded = false; + const s32 result = rcp(input); + divOut = result >> 16; + divIn = 0; + divInLoaded = false; #ifdef SIMD_SUPPORT - acc.l.single = vte.single; + acc.l.single = vte.single; #else - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i]; + } #endif - vd.element[ELEMENT_INDEX(de)] = result; + vd.element[ELEMENT_INDEX(de)] = result; } void RSP::vrcp(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - const VPR &vt = vpr[instr.vt()]; - SetVTE(vpr[instr.vt()], instr.e2()); - const int e = instr.e2() & 7; - const int de = DE(instr) & 7; - const s32 input = vt.selement[ELEMENT_INDEX(e)]; - const s32 result = rcp(input); - vd.element[ELEMENT_INDEX(de)] = result; - divOut = result >> 16; - divInLoaded = false; + VPR &vd = vpr[instr.vd()]; + const VPR &vt = vpr[instr.vt()]; + SetVTE(vpr[instr.vt()], instr.e2()); + const int e = instr.e2() & 7; + const int de = DE(instr) & 7; + const s32 input = vt.selement[ELEMENT_INDEX(e)]; + const s32 result = rcp(input); + vd.element[ELEMENT_INDEX(de)] = result; + divOut = result >> 16; + divInLoaded = false; #ifdef SIMD_SUPPORT - acc.l.single = vte.single; + acc.l.single = vte.single; #else - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i]; + } #endif } void RSP::vrsq(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - const VPR &vt = vpr[instr.vt()]; - SetVTE(vpr[instr.vt()], instr.e2()); - const int e = instr.e2() & 7; - const int de = instr.vs() & 7; - const s32 input = vt.selement[ELEMENT_INDEX(e)]; - const u32 result = rsq(input); - vd.element[ELEMENT_INDEX(de)] = result & 0xFFFF; - divOut = result >> 16; - divInLoaded = false; + VPR &vd = vpr[instr.vd()]; + const VPR &vt = vpr[instr.vt()]; + SetVTE(vpr[instr.vt()], instr.e2()); + const int e = instr.e2() & 7; + const int de = instr.vs() & 7; + const s32 input = vt.selement[ELEMENT_INDEX(e)]; + const u32 result = rsq(input); + vd.element[ELEMENT_INDEX(de)] = result & 0xFFFF; + divOut = result >> 16; + divInLoaded = false; #ifdef SIMD_SUPPORT - acc.l.single = vte.single; + acc.l.single = vte.single; #else - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i]; + } #endif } // from nall, in ares static FORCE_INLINE s64 sclip(const s64 x, const u32 bits) { - const u64 b = 1ull << (bits - 1); - const u64 m = b * 2 - 1; - return ((x & m) ^ b) - b; + const u64 b = 1ull << (bits - 1); + const u64 m = b * 2 - 1; + return ((x & m) ^ b) - b; } void RSP::vrndn(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], instr.e2()); + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], instr.e2()); - for (int i = 0; i < 8; i++) { - s32 product = vte.selement[i]; + for (int i = 0; i < 8; i++) { + s32 product = vte.selement[i]; - if (instr.vs() & 1) { - product <<= 16; + if (instr.vs() & 1) { + product <<= 16; + } + + s64 accum = 0; + accum |= acc.h.element[i]; + accum <<= 16; + accum |= acc.m.element[i]; + accum <<= 16; + accum |= acc.l.element[i]; + accum <<= 16; + accum >>= 16; + + if (accum < 0) { + accum = sclip(accum + product, 48); + } + + acc.h.element[i] = accum >> 32; + acc.m.element[i] = accum >> 16; + acc.l.element[i] = accum >> 0; + vd.element[i] = signedClamp(accum >> 16); } - - s64 accum = 0; - accum |= acc.h.element[i]; - accum <<= 16; - accum |= acc.m.element[i]; - accum <<= 16; - accum |= acc.l.element[i]; - accum <<= 16; - accum >>= 16; - - if (accum < 0) { - accum = sclip(accum + product, 48); - } - - acc.h.element[i] = accum >> 32; - acc.m.element[i] = accum >> 16; - acc.l.element[i] = accum >> 0; - vd.element[i] = signedClamp(accum >> 16); - } } void RSP::vrndp(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], instr.e2()); + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], instr.e2()); - for (int i = 0; i < 8; i++) { - s32 product = vte.selement[i]; + for (int i = 0; i < 8; i++) { + s32 product = vte.selement[i]; - if (instr.vs() & 1) { - product <<= 16; + if (instr.vs() & 1) { + product <<= 16; + } + + s64 accum = 0; + accum |= acc.h.element[i]; + accum <<= 16; + accum |= acc.m.element[i]; + accum <<= 16; + accum |= acc.l.element[i]; + accum <<= 16; + accum >>= 16; + + if (accum >= 0) { + accum = sclip(accum + product, 48); + } + + acc.h.element[i] = accum >> 32; + acc.m.element[i] = accum >> 16; + acc.l.element[i] = accum >> 0; + vd.element[i] = signedClamp(accum >> 16); } - - s64 accum = 0; - accum |= acc.h.element[i]; - accum <<= 16; - accum |= acc.m.element[i]; - accum <<= 16; - accum |= acc.l.element[i]; - accum <<= 16; - accum >>= 16; - - if (accum >= 0) { - accum = sclip(accum + product, 48); - } - - acc.h.element[i] = accum >> 32; - acc.m.element[i] = accum >> 16; - acc.l.element[i] = accum >> 0; - vd.element[i] = signedClamp(accum >> 16); - } } void RSP::vrsql(const Instruction instr) { - VPR &vd = vpr[instr.vd()]; - const VPR &vt = vpr[instr.vt()]; - SetVTE(vpr[instr.vt()], instr.e2()); - const int e = instr.e2() & 7; - const int de = DE(instr) & 7; + VPR &vd = vpr[instr.vd()]; + const VPR &vt = vpr[instr.vt()]; + SetVTE(vpr[instr.vt()], instr.e2()); + const int e = instr.e2() & 7; + const int de = DE(instr) & 7; - s32 input; - if (divInLoaded) { - input = (divIn << 16) | vt.element[ELEMENT_INDEX(e)]; - } else { - input = vt.selement[ELEMENT_INDEX(e)]; - } + s32 input; + if (divInLoaded) { + input = (divIn << 16) | vt.element[ELEMENT_INDEX(e)]; + } else { + input = vt.selement[ELEMENT_INDEX(e)]; + } - const u32 result = rsq(input); - divOut = result >> 16; - divInLoaded = false; + const u32 result = rsq(input); + divOut = result >> 16; + divInLoaded = false; #ifdef SIMD_SUPPORT - acc.l.single = vte.single; + acc.l.single = vte.single; #else - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i]; + } #endif - vd.element[ELEMENT_INDEX(de)] = result; + vd.element[ELEMENT_INDEX(de)] = result; } void RSP::vrcph(const Instruction instr) { - const int e = instr.e2() & 7; - const int de = DE(instr) & 7; - VPR &vd = vpr[instr.vd()]; - const VPR &vt = vpr[instr.vt()]; - SetVTE(vpr[instr.vt()], instr.e2()); + const int e = instr.e2() & 7; + const int de = DE(instr) & 7; + VPR &vd = vpr[instr.vd()]; + const VPR &vt = vpr[instr.vt()]; + SetVTE(vpr[instr.vt()], instr.e2()); #ifdef SIMD_SUPPORT - acc.l.single = vte.single; + acc.l.single = vte.single; #else - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i]; + } #endif - vd.element[ELEMENT_INDEX(de)] = divOut; - divIn = vt.element[ELEMENT_INDEX(e)]; - divInLoaded = true; + vd.element[ELEMENT_INDEX(de)] = divOut; + divIn = vt.element[ELEMENT_INDEX(e)]; + divInLoaded = true; } void RSP::vsar(const Instruction instr) { - const u8 e = instr.e2(); - VPR &vd = vpr[instr.vd()]; - switch (e) { - case 0x8: + const u8 e = instr.e2(); + VPR &vd = vpr[instr.vd()]; + switch (e) { + case 0x8: #ifdef SIMD_SUPPORT - vd.single = acc.h.single; + vd.single = acc.h.single; #else - for (int i = 0; i < 8; i++) { - vd.element[i] = acc.h.element[i]; - } + for (int i = 0; i < 8; i++) { + vd.element[i] = acc.h.element[i]; + } #endif - break; - case 0x9: + break; + case 0x9: #ifdef SIMD_SUPPORT - vd.single = acc.m.single; + vd.single = acc.m.single; #else - for (int i = 0; i < 8; i++) { - vd.element[i] = acc.m.element[i]; - } + for (int i = 0; i < 8; i++) { + vd.element[i] = acc.m.element[i]; + } #endif - break; - case 0xA: + break; + case 0xA: #ifdef SIMD_SUPPORT - vd.single = acc.l.single; + vd.single = acc.l.single; #else - for (int i = 0; i < 8; i++) { - vd.element[i] = acc.l.element[i]; - } + for (int i = 0; i < 8; i++) { + vd.element[i] = acc.l.element[i]; + } #endif - break; - default: + break; + default: #ifdef SIMD_SUPPORT - vd.single = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, 0); + vd.single = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, 0); #else - for (int i = 0; i < 8; i++) { - vd.element[i] = 0; - } + for (int i = 0; i < 8; i++) { + vd.element[i] = 0; + } #endif - break; - } + break; + } } void RSP::vsubc(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const u32 result = vs.element[i] - vte.element[i]; - acc.l.element[i] = result; - vd.element[i] = result; + for (int i = 0; i < 8; i++) { + const u32 result = vs.element[i] - vte.element[i]; + acc.l.element[i] = result; + vd.element[i] = result; - vco.l.element[i] = (result >> 16) & 1 ? 0xffff : 0; - vco.h.element[i] = result != 0 ? 0xffff : 0; - } + vco.l.element[i] = (result >> 16) & 1 ? 0xffff : 0; + vco.h.element[i] = result != 0 ? 0xffff : 0; + } } void RSP::vsub(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - const s32 result = vs.selement[i] - vte.selement[i] - (vco.l.element[i] != 0); - acc.l.element[i] = result; - vd.element[i] = signedClamp(result); + for (int i = 0; i < 8; i++) { + const s32 result = vs.selement[i] - vte.selement[i] - (vco.l.element[i] != 0); + acc.l.element[i] = result; + vd.element[i] = signedClamp(result); - vco.l.element[i] = 0; - vco.h.element[i] = 0; - } + vco.l.element[i] = 0; + vco.h.element[i] = 0; + } } void RSP::vmrg(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; - vd.element[i] = acc.l.element[i]; + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; + vd.element[i] = acc.l.element[i]; - vco.l.element[i] = vco.h.element[i] = 0; - } + vco.l.element[i] = vco.h.element[i] = 0; + } } void RSP::vxor(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i] ^ vs.element[i]; - vd.element[i] = acc.l.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i] ^ vs.element[i]; + vd.element[i] = acc.l.element[i]; + } } void RSP::vnxor(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - acc.l.element[i] = ~(vte.element[i] ^ vs.element[i]); - vd.element[i] = acc.l.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = ~(vte.element[i] ^ vs.element[i]); + vd.element[i] = acc.l.element[i]; + } } void RSP::vand(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i] & vs.element[i]; - vd.element[i] = acc.l.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i] & vs.element[i]; + vd.element[i] = acc.l.element[i]; + } } void RSP::vnand(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - acc.l.element[i] = ~(vte.element[i] & vs.element[i]); - vd.element[i] = acc.l.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = ~(vte.element[i] & vs.element[i]); + vd.element[i] = acc.l.element[i]; + } } void RSP::vnor(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - acc.l.element[i] = ~(vte.element[i] | vs.element[i]); - vd.element[i] = acc.l.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = ~(vte.element[i] | vs.element[i]); + vd.element[i] = acc.l.element[i]; + } } void RSP::vor(const Instruction instr) { - const int e = instr.e2(); - const VPR &vs = vpr[instr.vs()]; - VPR &vd = vpr[instr.vd()]; - SetVTE(vpr[instr.vt()], e); + const int e = instr.e2(); + const VPR &vs = vpr[instr.vs()]; + VPR &vd = vpr[instr.vd()]; + SetVTE(vpr[instr.vt()], e); - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i] | vs.element[i]; - vd.element[i] = acc.l.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i] | vs.element[i]; + vd.element[i] = acc.l.element[i]; + } } void RSP::vzero(const Instruction instr) { - const VPR &vs = vpr[instr.vs()]; - SetVTE(vpr[instr.vt()], instr.e2()); - VPR &vd = vpr[instr.vd()]; + const VPR &vs = vpr[instr.vs()]; + SetVTE(vpr[instr.vt()], instr.e2()); + VPR &vd = vpr[instr.vd()]; - for (int i = 0; i < 8; i++) { - acc.l.element[i] = vte.element[i] + vs.element[i]; - } + for (int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i] + vs.element[i]; + } - memset(&vd, 0, sizeof(VPR)); + memset(&vd, 0, sizeof(VPR)); } void RSP::mfc0(const RDP &rdp, const Instruction instr) { gpr[instr.rt()] = GetCop0Reg(*this, rdp, instr.rd()); } -void RSP::mtc0(const Instruction instr) const { - Mem& mem = Core::GetMem(); - SetCop0Reg(mem, instr.rd(), gpr[instr.rt()]); +void RSP::mtc0(const Instruction instr) const { + Mem &mem = Core::GetMem(); + SetCop0Reg(mem, instr.rd(), gpr[instr.rt()]); } void RSP::mfc2(const Instruction instr) { - const u8 hi = vpr[instr.rd()].byte[BYTE_INDEX(instr.e1())]; - const u8 lo = vpr[instr.rd()].byte[BYTE_INDEX((instr.e1() + 1) & 0xF)]; - const s16 elem = hi << 8 | lo; - gpr[instr.rt()] = elem; + const u8 hi = vpr[instr.rd()].byte[BYTE_INDEX(instr.e1())]; + const u8 lo = vpr[instr.rd()].byte[BYTE_INDEX((instr.e1() + 1) & 0xF)]; + const s16 elem = hi << 8 | lo; + gpr[instr.rt()] = elem; } void RSP::mtc2(const Instruction instr) { - const u16 element = gpr[instr.rt()]; - const u8 lo = element; - const u8 hi = element >> 8; - vpr[instr.rd()].byte[BYTE_INDEX(instr.e1())] = hi; - if (instr.e1() < 15) { - vpr[instr.rd()].byte[BYTE_INDEX(instr.e1() + 1)] = lo; - } + const u16 element = gpr[instr.rt()]; + const u8 lo = element; + const u8 hi = element >> 8; + vpr[instr.rd()].byte[BYTE_INDEX(instr.e1())] = hi; + if (instr.e1() < 15) { + vpr[instr.rd()].byte[BYTE_INDEX(instr.e1() + 1)] = lo; + } } } // namespace n64 diff --git a/src/frontend/EmuThread.cpp b/src/frontend/EmuThread.cpp index 1c8e01f..626a8d5 100644 --- a/src/frontend/EmuThread.cpp +++ b/src/frontend/EmuThread.cpp @@ -14,9 +14,9 @@ void EmuThread::run() { const auto index = e.gdevice.which; gamepad = SDL_OpenGamepad(index); - warn("Found controller!"); - warn("Name: {}", SDL_GetGamepadName(gamepad)); - warn("Vendor: {}", SDL_GetGamepadVendor(gamepad)); + ircolib::warn("Found controller!"); + ircolib::warn("Name: {}", SDL_GetGamepadName(gamepad)); + ircolib::warn("Vendor: {}", SDL_GetGamepadVendor(gamepad)); } } diff --git a/src/frontend/KaizenGui.cpp b/src/frontend/KaizenGui.cpp index c918591..cf08195 100644 --- a/src/frontend/KaizenGui.cpp +++ b/src/frontend/KaizenGui.cpp @@ -36,26 +36,8 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User connect(romsListTable, &RomsListTable::cleared, this, [&] { centralWidget->setCurrentWidget(romPathNotSet); }); - connect(romsListTable, &RomsListTable::populateFinished, this, [&] { - for (int i = 0; i < romsListTable->size(); i++) { - const auto &[countryCode, version, _, name, regions, lastPlayed, timePlayed] = (*romsListTable)[i]; - - romsListTable->insertRow(i); - romsListTable->setItem( - i, 0, - new QTableWidgetItem( - std::format("{} ({}) (Rev {})", name, n64::GameDB::regionCodeToReadable(countryCode), version) - .c_str())); - romsListTable->setItem(i, 1, new QTableWidgetItem(regions.c_str())); - romsListTable->setItem(i, 2, new QTableWidgetItem(lastPlayed.c_str())); - romsListTable->setItem(i, 3, new QTableWidgetItem(timePlayed.c_str())); - } - romsListTable->resizeRowsToContents(); - centralWidget->setCurrentWidget(romsListTable); - }); - connect(romsListTable, &QTableWidget::cellDoubleClicked, this, - [&](int row, int) { LoadROM((*romsListTable)[row].path); }); + [&](int row, int) { LoadROM(romsListTable->GetPathForClickedCell(row)); }); installEventFilter(this); diff --git a/src/frontend/RenderWidget.cpp b/src/frontend/RenderWidget.cpp index 536569c..1d43ed4 100644 --- a/src/frontend/RenderWidget.cpp +++ b/src/frontend/RenderWidget.cpp @@ -16,7 +16,7 @@ static CompositorCategory GetOSCompositorCategory() { if (platform_name == QStringLiteral("cocoa") || platform_name == QStringLiteral("ios")) return CompositorCategory::MacOS; - warn("Unknown Qt platform!"); + ircolib::warn("Unknown Qt platform!"); return CompositorCategory::Windows; } @@ -34,7 +34,7 @@ RenderWidget::RenderWidget() { } if (!Vulkan::Context::init_loader(nullptr)) { - panic("Could not initialize Vulkan ICD"); + ircolib::panic("Could not initialize Vulkan ICD"); } qtVkInstanceFactory = std::make_unique(); diff --git a/src/frontend/RomsList.cpp b/src/frontend/RomsList.cpp index e8ae531..159e54f 100644 --- a/src/frontend/RomsList.cpp +++ b/src/frontend/RomsList.cpp @@ -13,38 +13,31 @@ RomsListTable::RomsListTable(GeneralSettings *general) { setSelectionBehavior(QAbstractItemView::SelectRows); setEditTriggers(QAbstractItemView::NoEditTriggers); setSortingEnabled(true); - setColumnCount(4); + setColumnCount(5); setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); setHorizontalHeaderItem(1, new QTableWidgetItem("Regions")); setHorizontalHeaderItem(2, new QTableWidgetItem("Last played")); setHorizontalHeaderItem(3, new QTableWidgetItem("Time played")); + setHorizontalHeaderItem(4, new QTableWidgetItem("__path__")); + hideColumn(4); connect(general, &GeneralSettings::romFolderSelected, this, [&] { - std::thread popThread([&] { - populate(Options::GetRomsPath()); - emit populateFinished(); - }); - + std::thread popThread([&] { populate(Options::GetRomsPath()); }); popThread.detach(); }); connect(general, &GeneralSettings::romFolderCleared, this, [&] { - for (int i = 0; i < rowCount(); i++) - removeRow(i); - romsList = {}; + clearContents(); emit cleared(); }); - std::thread popThread([&] { - populate(Options::GetRomsPath()); - emit populateFinished(); - }); - + std::thread popThread([&] { populate(Options::GetRomsPath()); }); popThread.detach(); } void RomsListTable::populate(const std::string &romsPath) { if (!romsPath.empty()) { + int i = 0; for (const auto &file : fs::recursive_directory_iterator{romsPath}) { if (!file.is_regular_file()) continue; @@ -67,8 +60,17 @@ void RomsListTable::populate(const std::string &romsPath) { if (rom.gameNameDB.empty()) rom.gameNameDB = fs::path(filename).stem().string(); - romsList.push_back( - {rom.header.countryCode, rom.header.version, filename, rom.gameNameDB, regions, "Never", "0h 00m 00s"}); + insertRow(i); + setItem(i, 0, + new QTableWidgetItem(std::format("{} ({}) (Rev {})", rom.gameNameDB, + n64::GameDB::regionCodeToReadable(rom.header.countryCode), + rom.header.version) + .c_str())); + setItem(i, 1, new QTableWidgetItem(regions.c_str())); + setItem(i, 2, new QTableWidgetItem("Never")); + setItem(i, 3, new QTableWidgetItem("0h 0m 0s")); + setItem(i, 4, new QTableWidgetItem(filename.c_str())); + i++; } } } diff --git a/src/frontend/RomsList.hpp b/src/frontend/RomsList.hpp index 74e5416..87616a4 100644 --- a/src/frontend/RomsList.hpp +++ b/src/frontend/RomsList.hpp @@ -19,14 +19,12 @@ class RomsListTable : public QTableWidget { void populate(const std::string &); public: - std::vector romsList; RomsListTable(GeneralSettings *); - size_t size() { return romsList.size(); } + size_t size() { return rowCount(); } - RomsListEntry &operator[](const size_t i) { return romsList[i]; } + std::string GetPathForClickedCell(int i) const { return item(i, 4)->text().toStdString(); } signals: - void populateFinished(); void cleared(); }; diff --git a/src/frontend/Settings/CPUSettings.cpp b/src/frontend/Settings/CPUSettings.cpp index 18bc4e1..a93577d 100644 --- a/src/frontend/Settings/CPUSettings.cpp +++ b/src/frontend/Settings/CPUSettings.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include CPUSettings::CPUSettings() : settings(QSettings::UserScope) { types = new QComboBox(); diff --git a/src/frontend/Settings/GeneralSettings.cpp b/src/frontend/Settings/GeneralSettings.cpp index fba1725..8267ce7 100644 --- a/src/frontend/Settings/GeneralSettings.cpp +++ b/src/frontend/Settings/GeneralSettings.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) { diff --git a/src/types.hpp b/src/types.hpp index 91e4359..ebbf132 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -1,11 +1,5 @@ #pragma once #include -#ifdef USE_NEON -#include -#else -#include -#include -#endif using u8 = ircolib::u8; using u16 = ircolib::u16; diff --git a/src/utils/File.cpp b/src/utils/File.cpp index c384edb..ae64a8c 100644 --- a/src/utils/File.cpp +++ b/src/utils/File.cpp @@ -4,55 +4,56 @@ namespace Util { std::vector OpenROM(const std::string &filename, size_t &sizeAdjusted) { - auto buf = ircolib::ReadFileBinary(filename); - sizeAdjusted = ircolib::NextPow2(buf.size()); - return buf; + auto buf = ircolib::read_file_binary(filename); + sizeAdjusted = ircolib::next_pow2(buf.size()); + return buf; } std::vector OpenArchive(const std::string &path, size_t &sizeAdjusted) { - const auto stream = ar_open_file(fs::path(path).string().c_str()); + const auto stream = ar_open_file(fs::path(path).string().c_str()); - if (!stream) { - panic("Could not open archive! Are you sure it's an archive?"); - } + if (!stream) { + ircolib::panic("Could not open archive! Are you sure it's an archive?"); + } - ar_archive *archive = ar_open_zip_archive(stream, false); + ar_archive *archive = ar_open_zip_archive(stream, false); - if (!archive) - archive = ar_open_rar_archive(stream); - if (!archive) - archive = ar_open_7z_archive(stream); - if (!archive) - archive = ar_open_tar_archive(stream); + if (!archive) + archive = ar_open_rar_archive(stream); + if (!archive) + archive = ar_open_7z_archive(stream); + if (!archive) + archive = ar_open_tar_archive(stream); - if (!archive) { - ar_close(stream); - panic("Could not open archive! Are you sure it's a supported archive? (7z, zip, rar and tar are supported)"); - } + if (!archive) { + ar_close(stream); + ircolib::panic( + "Could not open archive! Are you sure it's a supported archive? (7z, zip, rar and tar are supported)"); + } - std::vector buf{}; + std::vector buf{}; - std::vector rom_exts{".n64", ".z64", ".v64", ".N64", ".Z64", ".V64"}; + std::vector rom_exts{".n64", ".z64", ".v64", ".N64", ".Z64", ".V64"}; - while (ar_parse_entry(archive)) { - auto filename = ar_entry_get_name(archive); - auto extension = fs::path(filename).extension(); + while (ar_parse_entry(archive)) { + auto filename = ar_entry_get_name(archive); + auto extension = fs::path(filename).extension(); - if (std::ranges::any_of(rom_exts, [&](const auto &x) { return extension == x; })) { - const auto size = ar_entry_get_size(archive); - sizeAdjusted = ircolib::NextPow2(size); - buf.resize(sizeAdjusted); - ar_entry_uncompress(archive, buf.data(), size); - break; + if (std::ranges::any_of(rom_exts, [&](const auto &x) { return extension == x; })) { + const auto size = ar_entry_get_size(archive); + sizeAdjusted = ircolib::next_pow2(size); + buf.resize(sizeAdjusted); + ar_entry_uncompress(archive, buf.data(), size); + break; + } + + ar_close_archive(archive); + ar_close(stream); + ircolib::panic("Could not find any rom image in the archive!"); } ar_close_archive(archive); ar_close(stream); - panic("Could not find any rom image in the archive!"); - } - - ar_close_archive(archive); - ar_close(stream); - return buf; + return buf; } -} \ No newline at end of file +} // namespace Util diff --git a/src/utils/File.hpp b/src/utils/File.hpp index 2e3f114..f43a051 100644 --- a/src/utils/File.hpp +++ b/src/utils/File.hpp @@ -1,9 +1,10 @@ #pragma once #include -#include +#include #include #include #include +#include namespace fs = std::filesystem; diff --git a/src/utils/log.hpp b/src/utils/log.hpp deleted file mode 100644 index 3163564..0000000 --- a/src/utils/log.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include -#include -#include -#if !defined(NDEBUG) && !defined(_WIN32) -#include -#endif - -namespace Util { -enum LogLevel : u8 { Trace, Debug, Info, Warn, Error, Always }; - -#ifndef NDEBUG -static constexpr auto globalLogLevel = Debug; -#else -static constexpr auto globalLogLevel = Warn; -#endif - -template -void print(const std::format_string fmt, Args... args) { - if (messageType >= globalLogLevel) { - if (messageType <= Debug) { -#ifndef NDEBUG - std::println(fmt, std::forward(args)...); -#endif - } else { - std::println(fmt, std::forward(args)...); - } - } -} - -#define panic(fmt, ...) \ - do { \ - Util::print("[FATAL] " fmt __VA_OPT__(, ) __VA_ARGS__); \ - exit(-1); \ - } \ - while (0) -#define error(fmt, ...) \ - do { \ - Util::print("[ERROR] " fmt __VA_OPT__(, ) __VA_ARGS__); \ - } \ - while (0) -#define warn(fmt, ...) \ - do { \ - Util::print("[WARN] " fmt __VA_OPT__(, ) __VA_ARGS__); \ - } \ - while (0) -#define info(fmt, ...) \ - do { \ - Util::print("[INFO] " fmt __VA_OPT__(, ) __VA_ARGS__); \ - } \ - while (0) -#define debug(fmt, ...) \ - do { \ - Util::print("[DEBUG] " fmt __VA_OPT__(, ) __VA_ARGS__); \ - } \ - while (0) -#define trace(fmt, ...) \ - do { \ - Util::print("[TRACE] " fmt __VA_OPT__(, ) __VA_ARGS__); \ - } \ - while (0) -#define always(fmt, ...) \ - do { \ - Util::print(fmt __VA_OPT__(, ) __VA_ARGS__); \ - } \ - while (0) -} // namespace Util