Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for 0.0.30 #14959

Merged
merged 18 commits into from Jan 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
99 changes: 43 additions & 56 deletions Utilities/BitField.h
Expand Up @@ -15,6 +15,9 @@ struct bf_base
using vtype = std::common_type_t<type>;
using utype = typename std::make_unsigned<vtype>::type;

static constexpr bool can_be_packed = N < (sizeof(int) * 8 + (std::is_unsigned_v<vtype> ? 1 : 0)) && sizeof(vtype) > sizeof(int);
using compact_type = std::conditional_t<can_be_packed, std::conditional_t<std::is_unsigned_v<vtype>, uint, int>, vtype>;

// Datatype bitsize
static constexpr uint bitmax = sizeof(T) * 8; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");

Expand All @@ -38,6 +41,7 @@ struct bf_t : bf_base<T, N>
using type = typename bf_t::type;
using vtype = typename bf_t::vtype;
using utype = typename bf_t::utype;
using compact_type = typename bf_t::compact_type;

// Field offset
static constexpr uint bitpos = I; static_assert(bitpos + N <= bf_t::bitmax, "bf_t<> error: I out of bounds");
Expand All @@ -48,47 +52,29 @@ struct bf_t : bf_base<T, N>
return static_cast<utype>(static_cast<utype>(bf_t::mask1 >> (bf_t::bitmax - bf_t::bitsize)) << bitpos);
}

// Bitfield extraction helper
template<typename T2, typename = void>
struct extract_impl
{
static_assert(!sizeof(T2), "bf_t<> error: Invalid type");
};

template<typename T2>
struct extract_impl<T2, std::enable_if_t<std::is_unsigned<T2>::value>>
// Bitfield extraction
static constexpr compact_type extract(const T& data) noexcept
{
// Load unsigned value
static constexpr T2 extract(const T& data)
if constexpr (std::is_signed_v<T>)
{
return static_cast<T2>((static_cast<utype>(data) >> bitpos) & bf_t::vmask);
// Load signed value (sign-extended)
return static_cast<compact_type>(static_cast<vtype>(static_cast<utype>(data) << (bf_t::bitmax - bitpos - N)) >> (bf_t::bitmax - N));
}
};

template<typename T2>
struct extract_impl<T2, std::enable_if_t<std::is_signed<T2>::value>>
{
// Load signed value (sign-extended)
static constexpr T2 extract(const T& data)
else
{
return static_cast<T2>(static_cast<vtype>(static_cast<utype>(data) << (bf_t::bitmax - bitpos - N)) >> (bf_t::bitmax - N));
// Load unsigned value
return static_cast<compact_type>((static_cast<utype>(data) >> bitpos) & bf_t::vmask);
}
};

// Bitfield extraction
static constexpr vtype extract(const T& data)
{
return extract_impl<vtype>::extract(data);
}

// Bitfield insertion
static constexpr vtype insert(vtype value)
static constexpr vtype insert(compact_type value)
{
return static_cast<vtype>((value & bf_t::vmask) << bitpos);
}

// Load bitfield value
constexpr operator vtype() const
constexpr operator compact_type() const noexcept
{
return extract(this->m_data);
}
Expand All @@ -100,72 +86,72 @@ struct bf_t : bf_base<T, N>
}

// Optimized bool conversion (must be removed if inappropriate)
explicit constexpr operator bool() const
explicit constexpr operator bool() const noexcept
{
return unshifted() != 0u;
}

// Store bitfield value
bf_t& operator =(vtype value)
bf_t& operator =(compact_type value) noexcept
{
this->m_data = static_cast<vtype>((this->m_data & ~data_mask()) | insert(value));
return *this;
}

vtype operator ++(int)
compact_type operator ++(int)
{
utype result = *this;
*this = static_cast<vtype>(result + 1);
compact_type result = *this;
*this = static_cast<compact_type>(result + 1u);
return result;
}

bf_t& operator ++()
{
return *this = *this + 1;
return *this = static_cast<compact_type>(*this + 1u);
}

vtype operator --(int)
compact_type operator --(int)
{
utype result = *this;
*this = static_cast<vtype>(result - 1);
compact_type result = *this;
*this = static_cast<compact_type>(result - 1u);
return result;
}

bf_t& operator --()
{
return *this = *this - 1;
return *this = static_cast<compact_type>(*this - 1u);
}

bf_t& operator +=(vtype right)
bf_t& operator +=(compact_type right)
{
return *this = *this + right;
return *this = static_cast<compact_type>(*this + right);
}

bf_t& operator -=(vtype right)
bf_t& operator -=(compact_type right)
{
return *this = *this - right;
return *this = static_cast<compact_type>(*this - right);
}

bf_t& operator *=(vtype right)
bf_t& operator *=(compact_type right)
{
return *this = *this * right;
return *this = static_cast<compact_type>(*this * right);
}

bf_t& operator &=(vtype right)
bf_t& operator &=(compact_type right)
{
this->m_data &= static_cast<vtype>(((static_cast<utype>(right) & bf_t::vmask) << bitpos) | ~(bf_t::vmask << bitpos));
this->m_data &= static_cast<vtype>(((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos) | ~(bf_t::vmask << bitpos));
return *this;
}

bf_t& operator |=(vtype right)
bf_t& operator |=(compact_type right)
{
this->m_data |= static_cast<vtype>((static_cast<utype>(right) & bf_t::vmask) << bitpos);
this->m_data |= static_cast<vtype>((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos);
return *this;
}

bf_t& operator ^=(vtype right)
bf_t& operator ^=(compact_type right)
{
this->m_data ^= static_cast<vtype>((static_cast<utype>(right) & bf_t::vmask) << bitpos);
this->m_data ^= static_cast<vtype>((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos);
return *this;
}
};
Expand All @@ -177,6 +163,7 @@ struct cf_t : bf_base<typename F::type, F::bitsize + cf_t<Fields...>::bitsize>
using type = typename cf_t::type;
using vtype = typename cf_t::vtype;
using utype = typename cf_t::utype;
using compact_type = typename cf_t::compact_type;

// Get disjunction of all "data" masks of concatenated values
static constexpr vtype data_mask()
Expand All @@ -185,25 +172,25 @@ struct cf_t : bf_base<typename F::type, F::bitsize + cf_t<Fields...>::bitsize>
}

// Extract all bitfields and concatenate
static constexpr vtype extract(const type& data)
static constexpr compact_type extract(const type& data)
{
return static_cast<vtype>(static_cast<utype>(F::extract(data)) << cf_t<Fields...>::bitsize | cf_t<Fields...>::extract(data));
return static_cast<compact_type>(static_cast<utype>(F::extract(data)) << cf_t<Fields...>::bitsize | cf_t<Fields...>::extract(data));
}

// Split bitfields and insert them
static constexpr vtype insert(vtype value)
static constexpr vtype insert(compact_type value)
{
return static_cast<vtype>(F::insert(value >> cf_t<Fields...>::bitsize) | cf_t<Fields...>::insert(value));
}

// Load value
constexpr operator vtype() const
constexpr operator compact_type() const noexcept
{
return extract(this->m_data);
}

// Store value
cf_t& operator =(vtype value)
cf_t& operator =(compact_type value) noexcept
{
this->m_data = (this->m_data & ~data_mask()) | insert(value);
return *this;
Expand Down Expand Up @@ -249,7 +236,7 @@ struct ff_t : bf_base<T, N>
}

// Get value
operator vtype() const
constexpr operator vtype() const noexcept
{
return V;
}
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/Modules/cellKb.cpp
Expand Up @@ -46,7 +46,7 @@ KeyboardHandlerBase::KeyboardHandlerBase(utils::serial* ar)

if (m_info.max_connect)
{
Emu.DeferDeserialization([this]()
Emu.PostponeInitCode([this]()
{
Init(m_info.max_connect);
auto lk = init.init();
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/Modules/cellMouse.cpp
Expand Up @@ -46,7 +46,7 @@ MouseHandlerBase::MouseHandlerBase(utils::serial* ar)

if (m_info.max_connect)
{
Emu.DeferDeserialization([this]()
Emu.PostponeInitCode([this]()
{
Init(m_info.max_connect);
auto lk = init.init();
Expand Down
18 changes: 14 additions & 4 deletions rpcs3/Emu/Cell/Modules/cellPad.cpp
Expand Up @@ -58,22 +58,24 @@ extern void sys_io_serialize(utils::serial& ar);
pad_info::pad_info(utils::serial& ar)
: max_connect(ar)
, port_setting(ar)
, reported_info(ar)
{
reported_info = {};
sys_io_serialize(ar);
}

void pad_info::save(utils::serial& ar)
{
USING_SERIALIZATION_VERSION(sys_io);

ar(max_connect, port_setting);
ar(max_connect, port_setting, reported_info);

sys_io_serialize(ar);
}

extern void send_sys_io_connect_event(usz index, u32 state);

void cellPad_NotifyStateChange(usz index, u64 /*state*/)
void cellPad_NotifyStateChange(usz index, u64 /*state*/, bool locked)
{
auto info = g_fxo->try_get<pad_info>();

Expand All @@ -82,7 +84,12 @@ void cellPad_NotifyStateChange(usz index, u64 /*state*/)
return;
}

std::lock_guard lock(pad::g_pad_mutex);
std::unique_lock lock(pad::g_pad_mutex, std::defer_lock);

if (locked)
{
lock.lock();
}

if (index >= info->get_max_connect())
{
Expand Down Expand Up @@ -158,7 +165,7 @@ void cellPad_NotifyStateChange(usz index, u64 /*state*/)

extern void pad_state_notify_state_change(usz index, u32 state)
{
cellPad_NotifyStateChange(index, state);
send_sys_io_connect_event(index, state);
}

error_code cellPadInit(ppu_thread& ppu, u32 max_connect)
Expand Down Expand Up @@ -1156,6 +1163,8 @@ error_code cellPadLddDataInsert(s32 handle, vm::ptr<CellPadData> data)

pads[handle]->ldd_data = *data;

cellPad_NotifyStateChange(handle, CELL_PAD_STATUS_CONNECTED, false);

return CELL_OK;
}

Expand Down Expand Up @@ -1204,6 +1213,7 @@ error_code cellPadLddUnregisterController(s32 handle)
return CELL_PAD_ERROR_NO_DEVICE;

handler->UnregisterLddPad(handle);
cellPad_NotifyStateChange(handle, CELL_PAD_STATUS_DISCONNECTED, false);

return CELL_OK;
}
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/Cell/Modules/cellPad.h
Expand Up @@ -49,6 +49,8 @@ struct pad_data_internal
u32 device_type;
u32 pclass_type;
u32 pclass_profile;

ENABLE_BITWISE_SERIALIZATION;
};

struct CellPadInfo
Expand Down
12 changes: 9 additions & 3 deletions rpcs3/Emu/Cell/Modules/sys_io_.cpp
Expand Up @@ -33,14 +33,14 @@ struct libio_sys_config
extern void sys_io_serialize(utils::serial& ar)
{
// Do not assign a serialization tag for now, call it from cellPad serialization
g_fxo->get<libio_sys_config>().save_or_load(ar);
ensure(g_fxo->try_get<libio_sys_config>())->save_or_load(ar);
}

extern void cellPad_NotifyStateChange(usz index, u64 state);
extern void cellPad_NotifyStateChange(usz index, u64 state, bool lock = true);

void config_event_entry(ppu_thread& ppu)
{
auto& cfg = g_fxo->get<libio_sys_config>();
auto& cfg = *ensure(g_fxo->try_get<libio_sys_config>());

if (!ppu.loaded_from_savestate)
{
Expand Down Expand Up @@ -106,6 +106,12 @@ std::unique_lock<shared_mutex> lock_lv2_mutex_alike(shared_mutex& mtx, ppu_threa

extern void send_sys_io_connect_event(usz index, u32 state)
{
if (Emu.IsStarting() || Emu.IsReady())
{
cellPad_NotifyStateChange(index, state);
return;
}

auto& cfg = g_fxo->get<libio_sys_config>();

auto lock = lock_lv2_mutex_alike(cfg.mtx, cpu_thread::get_current<ppu_thread>());
Expand Down
16 changes: 11 additions & 5 deletions rpcs3/Emu/Cell/PPUTranslator.cpp
Expand Up @@ -368,13 +368,19 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
const u64 base = m_reloc ? m_reloc->addr : 0;
const u32 caddr = m_info.segs[0].addr;
const u32 cend = caddr + m_info.segs[0].size - 1;
const u32 _target = ::narrow<u32>(target + base);
const u64 _target = target + base;

if (_target >= caddr && _target <= cend)
if (_target >= u32{umax})
{
std::unordered_set<u32> passed_targets{_target};
Call(GetType<void>(), "__error", m_thread, GetAddr(), m_ir->getInt32(*ensure(m_info.get_ptr<u32>(::narrow<u32>(m_addr + base)))));
m_ir->CreateRetVoid();
return;
}
else if (_target >= caddr && _target <= cend)
{
u32 target_last = static_cast<u32>(_target);

u32 target_last = _target;
std::unordered_set<u32> passed_targets{target_last};

// Try to follow unconditional branches as long as there is no infinite loop
while (target_last != _target)
Expand All @@ -396,7 +402,7 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
}

// Infinite loop detected
target_last = _target;
target_last = static_cast<u32>(_target);
}

// Odd destination
Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Emu/Cell/SPURecompiler.cpp
Expand Up @@ -4531,7 +4531,8 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
bool does_gpr_barrier_preceed_first_store(u32 i) const noexcept
{
const usz counter = store_context_ctr[i];
return counter != 1 && counter < store_context_first_id[i];
const usz first_id = store_context_first_id[i];
return counter != 1 && first_id != umax && counter < first_id;
}
};

Expand Down