Merge pull request #9964 from JosJuice/uncached-unaligned-writes

PowerPC: Implement broken masking for uncached unaligned writes
This commit is contained in:
Tilka
2021-08-04 22:23:07 +01:00
committed by GitHub
4 changed files with 229 additions and 158 deletions
@@ -323,14 +323,14 @@ void Interpreter::lwzu(UGeckoInstruction inst)
void Interpreter::stb(UGeckoInstruction inst)
{
PowerPC::Write_U8((u8)rGPR[inst.RS], Helper_Get_EA(PowerPC::ppcState, inst));
PowerPC::Write_U8(rGPR[inst.RS], Helper_Get_EA(PowerPC::ppcState, inst));
}
void Interpreter::stbu(UGeckoInstruction inst)
{
const u32 address = Helper_Get_EA_U(PowerPC::ppcState, inst);
PowerPC::Write_U8((u8)rGPR[inst.RS], address);
PowerPC::Write_U8(rGPR[inst.RS], address);
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{
rGPR[inst.RA] = address;
@@ -399,14 +399,14 @@ void Interpreter::stfsu(UGeckoInstruction inst)
void Interpreter::sth(UGeckoInstruction inst)
{
PowerPC::Write_U16((u16)rGPR[inst.RS], Helper_Get_EA(PowerPC::ppcState, inst));
PowerPC::Write_U16(rGPR[inst.RS], Helper_Get_EA(PowerPC::ppcState, inst));
}
void Interpreter::sthu(UGeckoInstruction inst)
{
const u32 address = Helper_Get_EA_U(PowerPC::ppcState, inst);
PowerPC::Write_U16((u16)rGPR[inst.RS], address);
PowerPC::Write_U16(rGPR[inst.RS], address);
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{
rGPR[inst.RA] = address;
@@ -731,7 +731,7 @@ void Interpreter::stbux(UGeckoInstruction inst)
{
const u32 address = Helper_Get_EA_UX(PowerPC::ppcState, inst);
PowerPC::Write_U8((u8)rGPR[inst.RS], address);
PowerPC::Write_U8(rGPR[inst.RS], address);
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{
rGPR[inst.RA] = address;
@@ -740,7 +740,7 @@ void Interpreter::stbux(UGeckoInstruction inst)
void Interpreter::stbx(UGeckoInstruction inst)
{
PowerPC::Write_U8((u8)rGPR[inst.RS], Helper_Get_EA_X(PowerPC::ppcState, inst));
PowerPC::Write_U8(rGPR[inst.RS], Helper_Get_EA_X(PowerPC::ppcState, inst));
}
void Interpreter::stfdux(UGeckoInstruction inst)
@@ -819,14 +819,14 @@ void Interpreter::stfsx(UGeckoInstruction inst)
void Interpreter::sthbrx(UGeckoInstruction inst)
{
PowerPC::Write_U16(Common::swap16((u16)rGPR[inst.RS]), Helper_Get_EA_X(PowerPC::ppcState, inst));
PowerPC::Write_U16_Swap(rGPR[inst.RS], Helper_Get_EA_X(PowerPC::ppcState, inst));
}
void Interpreter::sthux(UGeckoInstruction inst)
{
const u32 address = Helper_Get_EA_UX(PowerPC::ppcState, inst);
PowerPC::Write_U16((u16)rGPR[inst.RS], address);
PowerPC::Write_U16(rGPR[inst.RS], address);
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{
rGPR[inst.RA] = address;
@@ -835,7 +835,7 @@ void Interpreter::sthux(UGeckoInstruction inst)
void Interpreter::sthx(UGeckoInstruction inst)
{
PowerPC::Write_U16((u16)rGPR[inst.RS], Helper_Get_EA_X(PowerPC::ppcState, inst));
PowerPC::Write_U16(rGPR[inst.RS], Helper_Get_EA_X(PowerPC::ppcState, inst));
}
// lswi - bizarro string instruction
@@ -968,7 +968,7 @@ void Interpreter::stwbrx(UGeckoInstruction inst)
{
const u32 address = Helper_Get_EA_X(PowerPC::ppcState, inst);
PowerPC::Write_U32(Common::swap32(rGPR[inst.RS]), address);
PowerPC::Write_U32_Swap(rGPR[inst.RS], address);
}
// The following two instructions are for SMP communications. On a single
@@ -197,18 +197,16 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
}
else if (flags & BackPatchInfo::FLAG_STORE)
{
ARM64Reg temp = ARM64Reg::W0;
temp = ByteswapBeforeStore(this, temp, RS, flags, false);
if (temp != ARM64Reg::W0)
MOV(ARM64Reg::W0, temp);
const bool reverse = (flags & BackPatchInfo::FLAG_REVERSE) != 0;
if (flags & BackPatchInfo::FLAG_SIZE_32)
MOVP2R(ARM64Reg::X8, &PowerPC::Write_U32);
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U32_Swap : &PowerPC::Write_U32);
else if (flags & BackPatchInfo::FLAG_SIZE_16)
MOVP2R(ARM64Reg::X8, &PowerPC::Write_U16);
MOVP2R(ARM64Reg::X8, reverse ? &PowerPC::Write_U16_Swap : &PowerPC::Write_U16);
else
MOVP2R(ARM64Reg::X8, &PowerPC::Write_U8);
MOV(ARM64Reg::W0, RS);
BLR(ARM64Reg::X8);
}
else if (flags & BackPatchInfo::FLAG_ZERO_256)
File diff suppressed because it is too large Load Diff
+11 -9
View File
@@ -86,8 +86,8 @@ HostTryReadString(u32 address, size_t size = 0,
// Writes a value to emulated memory using the currently active MMU settings.
// If the write fails (eg. address does not correspond to a mapped address in the current address
// space), a PanicAlert will be shown to the user.
void HostWrite_U8(u8 var, u32 address);
void HostWrite_U16(u16 var, u32 address);
void HostWrite_U8(u32 var, u32 address);
void HostWrite_U16(u32 var, u32 address);
void HostWrite_U32(u32 var, u32 address);
void HostWrite_U64(u64 var, u32 address);
void HostWrite_F32(float var, u32 address);
@@ -111,9 +111,9 @@ struct TryWriteResult
// If the write succeeds, the returned TryWriteResult contains information on whether the given
// address had to be translated or not. Unlike the HostWrite functions, this does not raise a
// user-visible alert on failure.
TryWriteResult HostTryWriteU8(u8 var, const u32 address,
TryWriteResult HostTryWriteU8(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryWriteResult HostTryWriteU16(u16 var, const u32 address,
TryWriteResult HostTryWriteU16(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryWriteResult HostTryWriteU32(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
@@ -158,12 +158,12 @@ double Read_F64(u32 address);
u32 Read_U8_ZX(u32 address);
u32 Read_U16_ZX(u32 address);
void Write_U8(u8 var, u32 address);
void Write_U16(u16 var, u32 address);
void Write_U8(u32 var, u32 address);
void Write_U16(u32 var, u32 address);
void Write_U32(u32 var, u32 address);
void Write_U64(u64 var, u32 address);
void Write_U16_Swap(u16 var, u32 address);
void Write_U16_Swap(u32 var, u32 address);
void Write_U32_Swap(u32 var, u32 address);
void Write_U64_Swap(u64 var, u32 address);
@@ -199,16 +199,18 @@ constexpr int BAT_INDEX_SHIFT = 17;
constexpr u32 BAT_PAGE_SIZE = 1 << BAT_INDEX_SHIFT;
constexpr u32 BAT_MAPPED_BIT = 0x1;
constexpr u32 BAT_PHYSICAL_BIT = 0x2;
constexpr u32 BAT_RESULT_MASK = UINT32_C(~0x3);
constexpr u32 BAT_WI_BIT = 0x4;
constexpr u32 BAT_RESULT_MASK = UINT32_C(~0x7);
using BatTable = std::array<u32, 1 << (32 - BAT_INDEX_SHIFT)>; // 128 KB
extern BatTable ibat_table;
extern BatTable dbat_table;
inline bool TranslateBatAddess(const BatTable& bat_table, u32* address)
inline bool TranslateBatAddess(const BatTable& bat_table, u32* address, bool* wi)
{
u32 bat_result = bat_table[*address >> BAT_INDEX_SHIFT];
if ((bat_result & BAT_MAPPED_BIT) == 0)
return false;
*address = (bat_result & BAT_RESULT_MASK) | (*address & (BAT_PAGE_SIZE - 1));
*wi = (bat_result & BAT_WI_BIT) != 0;
return true;
}