JitArm64: Implement stwbrx/sthbrx

This commit is contained in:
JosJuice 2021-07-01 13:29:25 +02:00
parent d3ef5d4ca4
commit f666df72c0
5 changed files with 52 additions and 23 deletions

View File

@ -93,17 +93,14 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
else if (flags & BackPatchInfo::FLAG_STORE) else if (flags & BackPatchInfo::FLAG_STORE)
{ {
ARM64Reg temp = ARM64Reg::W0; ARM64Reg temp = ARM64Reg::W0;
if (flags & BackPatchInfo::FLAG_SIZE_32) temp = ByteswapBeforeStore(this, temp, RS, flags, true);
REV32(temp, RS);
else if (flags & BackPatchInfo::FLAG_SIZE_16)
REV16(temp, RS);
if (flags & BackPatchInfo::FLAG_SIZE_32) if (flags & BackPatchInfo::FLAG_SIZE_32)
STR(temp, MEM_REG, addr); STR(temp, MEM_REG, addr);
else if (flags & BackPatchInfo::FLAG_SIZE_16) else if (flags & BackPatchInfo::FLAG_SIZE_16)
STRH(temp, MEM_REG, addr); STRH(temp, MEM_REG, addr);
else else
STRB(RS, MEM_REG, addr); STRB(temp, MEM_REG, addr);
} }
else if (flags & BackPatchInfo::FLAG_ZERO_256) else if (flags & BackPatchInfo::FLAG_ZERO_256)
{ {
@ -200,7 +197,10 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
} }
else if (flags & BackPatchInfo::FLAG_STORE) else if (flags & BackPatchInfo::FLAG_STORE)
{ {
MOV(ARM64Reg::W0, RS); ARM64Reg temp = ARM64Reg::W0;
temp = ByteswapBeforeStore(this, temp, RS, flags, false);
if (temp != ARM64Reg::W0)
MOV(ARM64Reg::W0, temp);
if (flags & BackPatchInfo::FLAG_SIZE_32) if (flags & BackPatchInfo::FLAG_SIZE_32)
MOVP2R(ARM64Reg::X8, &PowerPC::Write_U32); MOVP2R(ARM64Reg::X8, &PowerPC::Write_U32);

View File

@ -239,21 +239,19 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
accessSize = 8; accessSize = 8;
LDR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr)); LDR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr));
ARM64Reg temp = ARM64Reg::W1;
temp = ByteswapBeforeStore(this, temp, RS, flags, true);
if (accessSize == 32) if (accessSize == 32)
{ STR(IndexType::Post, temp, ARM64Reg::X0, 4);
REV32(ARM64Reg::W1, RS);
STR(IndexType::Post, ARM64Reg::W1, ARM64Reg::X0, 4);
}
else if (accessSize == 16) else if (accessSize == 16)
{ STRH(IndexType::Post, temp, ARM64Reg::X0, 2);
REV16(ARM64Reg::W1, RS);
STRH(IndexType::Post, ARM64Reg::W1, ARM64Reg::X0, 2);
}
else else
{ STRB(IndexType::Post, temp, ARM64Reg::X0, 1);
STRB(IndexType::Post, RS, ARM64Reg::X0, 1);
}
STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr)); STR(IndexType::Unsigned, ARM64Reg::X0, PPC_REG, PPCSTATE_OFF(gather_pipe_ptr));
js.fifoBytesSinceCheck += accessSize >> 3; js.fifoBytesSinceCheck += accessSize >> 3;
} }
else if (jo.fastmem_arena && is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr)) else if (jo.fastmem_arena && is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
@ -261,7 +259,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
MOVI2R(XA, imm_addr); MOVI2R(XA, imm_addr);
EmitBackpatchRoutine(flags, true, false, RS, XA, BitSet32(0), BitSet32(0)); EmitBackpatchRoutine(flags, true, false, RS, XA, BitSet32(0), BitSet32(0));
} }
else if (mmio_address && !(flags & BackPatchInfo::FLAG_REVERSE)) else if (mmio_address)
{ {
MMIOWriteRegToAddr(Memory::mmio_mapping.get(), this, regs_in_use, fprs_in_use, RS, mmio_address, MMIOWriteRegToAddr(Memory::mmio_mapping.get(), this, regs_in_use, fprs_in_use, RS, mmio_address,
flags); flags);
@ -370,6 +368,7 @@ void JitArm64::stX(UGeckoInstruction inst)
switch (inst.OPCD) switch (inst.OPCD)
{ {
case 31: case 31:
regOffset = b;
switch (inst.SUBOP10) switch (inst.SUBOP10)
{ {
case 183: // stwux case 183: // stwux
@ -377,21 +376,24 @@ void JitArm64::stX(UGeckoInstruction inst)
[[fallthrough]]; [[fallthrough]];
case 151: // stwx case 151: // stwx
flags |= BackPatchInfo::FLAG_SIZE_32; flags |= BackPatchInfo::FLAG_SIZE_32;
regOffset = b;
break; break;
case 247: // stbux case 247: // stbux
update = true; update = true;
[[fallthrough]]; [[fallthrough]];
case 215: // stbx case 215: // stbx
flags |= BackPatchInfo::FLAG_SIZE_8; flags |= BackPatchInfo::FLAG_SIZE_8;
regOffset = b;
break; break;
case 439: // sthux case 439: // sthux
update = true; update = true;
[[fallthrough]]; [[fallthrough]];
case 407: // sthx case 407: // sthx
flags |= BackPatchInfo::FLAG_SIZE_16; flags |= BackPatchInfo::FLAG_SIZE_16;
regOffset = b; break;
case 662: // stwbrx
flags |= BackPatchInfo::FLAG_REVERSE | BackPatchInfo::FLAG_SIZE_32;
break;
case 918: // sthbrx
flags |= BackPatchInfo::FLAG_REVERSE | BackPatchInfo::FLAG_SIZE_16;
break; break;
} }
break; break;

View File

@ -249,8 +249,8 @@ constexpr std::array<GekkoOPTemplate, 107> table31{{
{247, &JitArm64::stX}, // stbux {247, &JitArm64::stX}, // stbux
// store bytereverse // store bytereverse
{662, &JitArm64::FallBackToInterpreter}, // stwbrx {662, &JitArm64::stX}, // stwbrx
{918, &JitArm64::FallBackToInterpreter}, // sthbrx {918, &JitArm64::stX}, // sthbrx
{661, &JitArm64::FallBackToInterpreter}, // stswx {661, &JitArm64::FallBackToInterpreter}, // stswx
{725, &JitArm64::FallBackToInterpreter}, // stswi {725, &JitArm64::FallBackToInterpreter}, // stswi

View File

@ -219,6 +219,28 @@ void ByteswapAfterLoad(ARM64XEmitter* emit, ARM64Reg dst_reg, ARM64Reg src_reg,
emit->MOV(dst_reg, src_reg); emit->MOV(dst_reg, src_reg);
} }
ARM64Reg ByteswapBeforeStore(ARM64XEmitter* emit, ARM64Reg tmp_reg, ARM64Reg src_reg, u32 flags,
bool want_reversed)
{
ARM64Reg dst_reg = src_reg;
if (want_reversed == !(flags & BackPatchInfo::FLAG_REVERSE))
{
if (flags & BackPatchInfo::FLAG_SIZE_32)
{
dst_reg = tmp_reg;
emit->REV32(dst_reg, src_reg);
}
else if (flags & BackPatchInfo::FLAG_SIZE_16)
{
dst_reg = tmp_reg;
emit->REV16(dst_reg, src_reg);
}
}
return dst_reg;
}
void MMIOLoadToReg(MMIO::Mapping* mmio, Arm64Gen::ARM64XEmitter* emit, BitSet32 gprs_in_use, void MMIOLoadToReg(MMIO::Mapping* mmio, Arm64Gen::ARM64XEmitter* emit, BitSet32 gprs_in_use,
BitSet32 fprs_in_use, ARM64Reg dst_reg, u32 address, u32 flags) BitSet32 fprs_in_use, ARM64Reg dst_reg, u32 address, u32 flags)
{ {
@ -247,6 +269,8 @@ void MMIOLoadToReg(MMIO::Mapping* mmio, Arm64Gen::ARM64XEmitter* emit, BitSet32
void MMIOWriteRegToAddr(MMIO::Mapping* mmio, Arm64Gen::ARM64XEmitter* emit, BitSet32 gprs_in_use, void MMIOWriteRegToAddr(MMIO::Mapping* mmio, Arm64Gen::ARM64XEmitter* emit, BitSet32 gprs_in_use,
BitSet32 fprs_in_use, ARM64Reg src_reg, u32 address, u32 flags) BitSet32 fprs_in_use, ARM64Reg src_reg, u32 address, u32 flags)
{ {
src_reg = ByteswapBeforeStore(emit, ARM64Reg::W1, src_reg, flags, false);
if (flags & BackPatchInfo::FLAG_SIZE_8) if (flags & BackPatchInfo::FLAG_SIZE_8)
{ {
MMIOWriteCodeGenerator<u8> gen(emit, gprs_in_use, fprs_in_use, src_reg, address); MMIOWriteCodeGenerator<u8> gen(emit, gprs_in_use, fprs_in_use, src_reg, address);

View File

@ -12,6 +12,9 @@
void ByteswapAfterLoad(Arm64Gen::ARM64XEmitter* emit, Arm64Gen::ARM64Reg dst_reg, void ByteswapAfterLoad(Arm64Gen::ARM64XEmitter* emit, Arm64Gen::ARM64Reg dst_reg,
Arm64Gen::ARM64Reg src_reg, u32 flags, bool is_reversed, bool is_extended); Arm64Gen::ARM64Reg src_reg, u32 flags, bool is_reversed, bool is_extended);
Arm64Gen::ARM64Reg ByteswapBeforeStore(Arm64Gen::ARM64XEmitter* emit, Arm64Gen::ARM64Reg tmp_reg,
Arm64Gen::ARM64Reg src_reg, u32 flags, bool want_reversed);
void MMIOLoadToReg(MMIO::Mapping* mmio, Arm64Gen::ARM64XEmitter* emit, BitSet32 gprs_in_use, void MMIOLoadToReg(MMIO::Mapping* mmio, Arm64Gen::ARM64XEmitter* emit, BitSet32 gprs_in_use,
BitSet32 fprs_in_use, Arm64Gen::ARM64Reg dst_reg, u32 address, u32 flags); BitSet32 fprs_in_use, Arm64Gen::ARM64Reg dst_reg, u32 address, u32 flags);