mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-06-02 20:55:23 -06:00
RawSPU: Implement 16-bit and 8-bit read MMIO
This commit is contained in:
parent
6a2ad0a0aa
commit
d7da6a713b
@ -1384,11 +1384,7 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a_size != 4)
|
||||
{
|
||||
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
|
||||
break;
|
||||
}
|
||||
bool handled = true;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
@ -1398,14 +1394,37 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
|
||||
case X64OP_LOAD_TEST:
|
||||
{
|
||||
u32 value;
|
||||
if (is_writing || !thread->read_reg(addr, value))
|
||||
const u32 addr_aligned = addr & -4;
|
||||
|
||||
if (addr % 4 + a_size > 4)
|
||||
{
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_writing || !thread->read_reg(addr_aligned, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjust value for 8-bit and 16-bit reads
|
||||
value >>= ((4 - a_size) * 8) - ((addr % 4) * 8);
|
||||
value &= a_size == 4 ? u32{umax} : ((1u << (a_size * 8)) - 1);
|
||||
|
||||
if (op != X64OP_LOAD_BE)
|
||||
{
|
||||
value = stx::se_storage<u32>::swap(value);
|
||||
if (a_size == 4)
|
||||
{
|
||||
value = stx::se_storage<u32>::swap(value);
|
||||
}
|
||||
else if (a_size == 2)
|
||||
{
|
||||
value = stx::se_storage<u16>::swap(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure(a_size == 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (op == X64OP_LOAD_CMP)
|
||||
@ -1440,12 +1459,35 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
|
||||
case X64OP_BEXTR:
|
||||
{
|
||||
u32 value;
|
||||
if (is_writing || !thread->read_reg(addr, value))
|
||||
const u32 addr_aligned = addr & -4;
|
||||
|
||||
if (addr % 4 + a_size > 4)
|
||||
{
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_writing || !thread->read_reg(addr_aligned, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = stx::se_storage<u32>::swap(value);
|
||||
// Adjust value for 8-bit and 16-bit reads
|
||||
value >>= ((4 - a_size) * 8) - ((addr % 4) * 8);
|
||||
value &= a_size == 4 ? u32{umax} : ((1u << (a_size * 8)) - 1);
|
||||
|
||||
if (a_size == 4)
|
||||
{
|
||||
value = stx::se_storage<u32>::swap(value);
|
||||
}
|
||||
else if (a_size == 2)
|
||||
{
|
||||
value = stx::se_storage<u16>::swap(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure(a_size == 1);
|
||||
}
|
||||
|
||||
u64 ctrl;
|
||||
if (!get_x64_reg_value(context, s_tls_reg3, d_size, i_size, ctrl))
|
||||
@ -1471,6 +1513,13 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
|
||||
case X64OP_STORE:
|
||||
case X64OP_STORE_BE:
|
||||
{
|
||||
if (a_size != 4)
|
||||
{
|
||||
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
u64 reg_value;
|
||||
if (!is_writing || !get_x64_reg_value(context, reg, d_size, i_size, reg_value))
|
||||
{
|
||||
@ -1489,12 +1538,19 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
|
||||
case X64OP_STOS:
|
||||
default:
|
||||
{
|
||||
sig_log.error("Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, i_size=%lld)", +op, +reg, d_size, i_size);
|
||||
sig_log.error("Invalid or unsupported operation (op=%d, addr=0x%x, reg=%d, d_size=%lld, i_size=%lld, a_size=%d)", +op, addr, +reg, d_size, i_size, a_size);
|
||||
report_opcode();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
sig_log.error("Invalid or unsupported operation (op=%d, addr=0x%x, reg=%d, d_size=%lld, i_size=%lld, a_size=%d)", +op, addr, +reg, d_size, i_size, a_size);
|
||||
report_opcode();
|
||||
break;
|
||||
}
|
||||
|
||||
// skip processed instruction
|
||||
RIP(context) += i_size;
|
||||
g_tls_fault_spu++;
|
||||
|
||||
@ -6430,8 +6430,6 @@ extern void resume_spu_thread_group_from_waiting(spu_thread& spu, std::array<sha
|
||||
|
||||
bool spu_thread::stop_and_signal(u32 code)
|
||||
{
|
||||
spu_log.trace("stop_and_signal(code=0x%x)", code);
|
||||
|
||||
auto set_status_npc = [&]()
|
||||
{
|
||||
status_npc.atomic_op([&](status_npc_sync_var& state)
|
||||
@ -6445,6 +6443,8 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||
|
||||
if (get_type() >= spu_type::raw)
|
||||
{
|
||||
spu_log.warning("stop_and_signal(code=0x%x)", code);
|
||||
|
||||
// Save next PC and current SPU Interrupt Status
|
||||
state += cpu_flag::stop + cpu_flag::wait + cpu_flag::ret;
|
||||
set_status_npc();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user