mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-06-03 21:25:04 -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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a_size != 4)
|
bool handled = true;
|
||||||
{
|
|
||||||
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
@ -1398,14 +1394,37 @@ bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t
|
|||||||
case X64OP_LOAD_TEST:
|
case X64OP_LOAD_TEST:
|
||||||
{
|
{
|
||||||
u32 value;
|
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;
|
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)
|
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)
|
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:
|
case X64OP_BEXTR:
|
||||||
{
|
{
|
||||||
u32 value;
|
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;
|
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;
|
u64 ctrl;
|
||||||
if (!get_x64_reg_value(context, s_tls_reg3, d_size, i_size, 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:
|
||||||
case X64OP_STORE_BE:
|
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;
|
u64 reg_value;
|
||||||
if (!is_writing || !get_x64_reg_value(context, reg, d_size, i_size, 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:
|
case X64OP_STOS:
|
||||||
default:
|
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();
|
report_opcode();
|
||||||
return false;
|
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
|
// skip processed instruction
|
||||||
RIP(context) += i_size;
|
RIP(context) += i_size;
|
||||||
g_tls_fault_spu++;
|
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)
|
bool spu_thread::stop_and_signal(u32 code)
|
||||||
{
|
{
|
||||||
spu_log.trace("stop_and_signal(code=0x%x)", code);
|
|
||||||
|
|
||||||
auto set_status_npc = [&]()
|
auto set_status_npc = [&]()
|
||||||
{
|
{
|
||||||
status_npc.atomic_op([&](status_npc_sync_var& state)
|
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)
|
if (get_type() >= spu_type::raw)
|
||||||
{
|
{
|
||||||
|
spu_log.warning("stop_and_signal(code=0x%x)", code);
|
||||||
|
|
||||||
// Save next PC and current SPU Interrupt Status
|
// Save next PC and current SPU Interrupt Status
|
||||||
state += cpu_flag::stop + cpu_flag::wait + cpu_flag::ret;
|
state += cpu_flag::stop + cpu_flag::wait + cpu_flag::ret;
|
||||||
set_status_npc();
|
set_status_npc();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user