s32 error_code::error_report(const fmt_type_info* sup, u64 arg, const fmt_type_info* sup2, u64 arg2) { static thread_local std::unordered_map<std::string, std::size_t> g_tls_error_stats; static thread_local std::string g_tls_error_str; if (g_tls_error_stats.empty()) { thread_ctrl::atexit([] { for (auto&& pair : g_tls_error_stats) { if (pair.second > 3) { LOG_ERROR(GENERAL, "Stat: %s [x%u]", pair.first, pair.second); } } }); } logs::channel* channel = &logs::GENERAL; logs::level level = logs::level::error; const char* func = "Unknown function"; if (auto thread = get_current_cpu_thread()) { if (g_system == system_type::ps3 && thread->id_type() == 1) { auto& ppu = static_cast<ppu_thread&>(*thread); if (ppu.last_function) { func = ppu.last_function; } } if (g_system == system_type::psv) { if (auto _func = static_cast<ARMv7Thread*>(thread)->last_function) { func = _func; } } } // Format log message (use preallocated buffer) g_tls_error_str.clear(); fmt::append(g_tls_error_str, "'%s' failed with 0x%08x%s%s%s%s", func, arg, sup ? " : " : "", std::make_pair(sup, arg), sup2 ? ", " : "", std::make_pair(sup2, arg2)); // Update stats and check log threshold const auto stat = ++g_tls_error_stats[g_tls_error_str]; if (stat <= 3) { channel->format(level, "%s [%u]", g_tls_error_str, stat); } return static_cast<s32>(arg); }
s32 error_code::error_report(const fmt_type_info* sup, u64 arg) { logs::channel* channel = &logs::GENERAL; logs::level level = logs::level::error; const char* func = "Unknown function"; if (auto thread = get_current_cpu_thread()) { if (g_system == system_type::ps3 && thread->id_type() == 1) { auto& ppu = static_cast<ppu_thread&>(*thread); // Filter some annoying reports switch (arg) { case CELL_ESRCH: case CELL_EDEADLK: { if (ppu.m_name == "_cellsurMixerMain" || ppu.m_name == "_sys_MixerChStripMain") { if (std::memcmp(ppu.last_function, "sys_mutex_lock", 15) == 0 || std::memcmp(ppu.last_function, "sys_lwmutex_lock", 17) == 0 || std::memcmp(ppu.last_function, "_sys_mutex_lock", 16) == 0 || std::memcmp(ppu.last_function, "_sys_lwmutex_lock", 18) == 0) { level = logs::level::trace; } } break; } } if (ppu.last_function) { func = ppu.last_function; } } if (g_system == system_type::psv) { if (auto _func = static_cast<ARMv7Thread*>(thread)->last_function) { func = _func; } } } channel->format(level, "'%s' failed with 0x%08x%s%s", func, arg, sup ? " : " : "", std::make_pair(sup, arg)); return static_cast<s32>(arg); }
void PPUThread::cpu_task() { //SetHostRoundingMode(FPSCR_RN_NEAR); if (custom_task) { if (check_status()) return; return custom_task(*this); } g_tls_log_prefix = [] { const auto cpu = static_cast<PPUThread*>(get_current_cpu_thread()); return fmt::format("%s [0x%08x]", cpu->get_name(), cpu->pc); }; const auto base = vm::_ptr<const u8>(0); // Select opcode table const auto& table = *( g_cfg_ppu_decoder.get() == ppu_decoder_type::precise ? &s_ppu_interpreter_precise.get_table() : g_cfg_ppu_decoder.get() == ppu_decoder_type::fast ? &s_ppu_interpreter_fast.get_table() : throw std::logic_error("Invalid PPU decoder")); v128 _op; decltype(&ppu_interpreter::UNK) func0, func1, func2, func3; while (true) { if (UNLIKELY(state.load())) { if (check_status()) return; } // Reinitialize { const auto _ops = _mm_shuffle_epi8(_mm_lddqu_si128(reinterpret_cast<const __m128i*>(base + pc)), _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3)); _op.vi = _ops; const v128 _i = v128::fromV(_mm_and_si128(_mm_or_si128(_mm_slli_epi32(_op.vi, 6), _mm_srli_epi32(_op.vi, 26)), _mm_set1_epi32(0x1ffff))); func0 = table[_i._u32[0]]; func1 = table[_i._u32[1]]; func2 = table[_i._u32[2]]; func3 = table[_i._u32[3]]; } while (LIKELY(func0(*this, { _op._u32[0] }))) { if (pc += 4, LIKELY(func1(*this, { _op._u32[1] }))) { if (pc += 4, LIKELY(func2(*this, { _op._u32[2] }))) { pc += 4; func0 = func3; const auto _ops = _mm_shuffle_epi8(_mm_lddqu_si128(reinterpret_cast<const __m128i*>(base + pc + 4)), _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3)); _op.vi = _mm_alignr_epi8(_ops, _op.vi, 12); const v128 _i = v128::fromV(_mm_and_si128(_mm_or_si128(_mm_slli_epi32(_op.vi, 6), _mm_srli_epi32(_op.vi, 26)), _mm_set1_epi32(0x1ffff))); func1 = table[_i._u32[1]]; func2 = table[_i._u32[2]]; func3 = table[_i._u32[3]]; if (UNLIKELY(state.load())) { break; } continue; } break; } break; } } }