diff --git a/Core/MIPS/ARM/ArmCompLoadStore.cpp b/Core/MIPS/ARM/ArmCompLoadStore.cpp index 1c62d7f986..e4e9131a28 100644 --- a/Core/MIPS/ARM/ArmCompLoadStore.cpp +++ b/Core/MIPS/ARM/ArmCompLoadStore.cpp @@ -385,6 +385,12 @@ namespace MIPSComp } } + void ArmJit::Comp_StoreSync(MIPSOpcode op) { + CONDITIONAL_DISABLE(LSU); + + DISABLE; + } + void ArmJit::Comp_Cache(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU); diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 829f53ef7d..04f1ac79d3 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -61,6 +61,7 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; + void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override; diff --git a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp index 08e7d541a6..9824f07001 100644 --- a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp +++ b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp @@ -434,6 +434,12 @@ namespace MIPSComp { } } + void Arm64Jit::Comp_StoreSync(MIPSOpcode op) { + CONDITIONAL_DISABLE(LSU); + + DISABLE; + } + void Arm64Jit::Comp_Cache(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU); diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index 3f81cd0a75..f3d6acc6a7 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -62,6 +62,7 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; + void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override; diff --git a/Core/MIPS/IR/IRCompLoadStore.cpp b/Core/MIPS/IR/IRCompLoadStore.cpp index cb1892d3d2..1a4aac5069 100644 --- a/Core/MIPS/IR/IRCompLoadStore.cpp +++ b/Core/MIPS/IR/IRCompLoadStore.cpp @@ -105,6 +105,30 @@ namespace MIPSComp { } } + void IRFrontend::Comp_StoreSync(MIPSOpcode op) { + CONDITIONAL_DISABLE(LSU); + + int offset = _IMM16; + MIPSGPReg rt = _RT; + MIPSGPReg rs = _RS; + // Note: still does something even if loading to zero. + + CheckMemoryBreakpoint(rs, offset); + + switch (op >> 26) { + case 48: // ll + ir.Write(IROp::Load32Linked, rt, rs, ir.AddConstant(offset)); + break; + + case 56: // sc + ir.Write(IROp::Store32Conditional, rt, rs, ir.AddConstant(offset)); + break; + + default: + INVALIDOP; + } + } + void IRFrontend::Comp_Cache(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU); diff --git a/Core/MIPS/IR/IRFrontend.h b/Core/MIPS/IR/IRFrontend.h index 0f9a1ab418..b53e053d73 100644 --- a/Core/MIPS/IR/IRFrontend.h +++ b/Core/MIPS/IR/IRFrontend.h @@ -18,6 +18,7 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; + void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override; diff --git a/Core/MIPS/IR/IRInst.cpp b/Core/MIPS/IR/IRInst.cpp index 116908c656..2f160772f2 100644 --- a/Core/MIPS/IR/IRInst.cpp +++ b/Core/MIPS/IR/IRInst.cpp @@ -73,6 +73,7 @@ static const IRMeta irMeta[] = { { IROp::Load32, "Load32", "GGC" }, { IROp::Load32Left, "Load32Left", "GGC", IRFLAG_SRC3DST }, { IROp::Load32Right, "Load32Right", "GGC", IRFLAG_SRC3DST }, + { IROp::Load32Linked, "Load32Linked", "GGC" }, { IROp::LoadFloat, "LoadFloat", "FGC" }, { IROp::LoadVec4, "LoadVec4", "VGC" }, { IROp::Store8, "Store8", "GGC", IRFLAG_SRC3 }, @@ -80,6 +81,7 @@ static const IRMeta irMeta[] = { { IROp::Store32, "Store32", "GGC", IRFLAG_SRC3 }, { IROp::Store32Left, "Store32Left", "GGC", IRFLAG_SRC3 }, { IROp::Store32Right, "Store32Right", "GGC", IRFLAG_SRC3 }, + { IROp::Store32Conditional, "Store32Conditional", "GGC", IRFLAG_SRC3DST }, { IROp::StoreFloat, "StoreFloat", "FGC", IRFLAG_SRC3 }, { IROp::StoreVec4, "StoreVec4", "VGC", IRFLAG_SRC3 }, { IROp::FAdd, "FAdd", "FFF" }, diff --git a/Core/MIPS/IR/IRInst.h b/Core/MIPS/IR/IRInst.h index d4eb47f49a..5f2aaeeb33 100644 --- a/Core/MIPS/IR/IRInst.h +++ b/Core/MIPS/IR/IRInst.h @@ -92,6 +92,7 @@ enum class IROp : u8 { Load32, Load32Left, Load32Right, + Load32Linked, LoadFloat, LoadVec4, @@ -100,6 +101,7 @@ enum class IROp : u8 { Store32, Store32Left, Store32Right, + Store32Conditional, StoreFloat, StoreVec4, diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp index 561adf6f25..699f92ddff 100644 --- a/Core/MIPS/IR/IRInterpreter.cpp +++ b/Core/MIPS/IR/IRInterpreter.cpp @@ -218,6 +218,11 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { mips->r[inst->dest] = (mips->r[inst->dest] & destMask) | (mem >> shift); break; } + case IROp::Load32Linked: + if (inst->dest != MIPS_REG_ZERO) + mips->r[inst->dest] = Memory::ReadUnchecked_U32(mips->r[inst->src1] + inst->constant); + mips->llBit = 1; + break; case IROp::LoadFloat: mips->f[inst->dest] = Memory::ReadUnchecked_Float(mips->r[inst->src1] + inst->constant); break; @@ -251,6 +256,16 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { Memory::WriteUnchecked_U32(result, addr & 0xfffffffc); break; } + case IROp::Store32Conditional: + if (mips->llBit) { + Memory::WriteUnchecked_U32(mips->r[inst->src3], mips->r[inst->src1] + inst->constant); + if (inst->dest != MIPS_REG_ZERO) { + mips->r[inst->dest] = 1; + } + } else if (inst->dest != MIPS_REG_ZERO) { + mips->r[inst->dest] = 0; + } + break; case IROp::StoreFloat: Memory::WriteUnchecked_Float(mips->f[inst->src3], mips->r[inst->src1] + inst->constant); break; diff --git a/Core/MIPS/IR/IRPassSimplify.cpp b/Core/MIPS/IR/IRPassSimplify.cpp index 3d277ebbae..bfd31651a7 100644 --- a/Core/MIPS/IR/IRPassSimplify.cpp +++ b/Core/MIPS/IR/IRPassSimplify.cpp @@ -604,6 +604,7 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts case IROp::Store32: case IROp::Store32Left: case IROp::Store32Right: + case IROp::Store32Conditional: if (gpr.IsImm(inst.src1) && inst.src1 != inst.dest) { gpr.MapIn(inst.dest); out.Write(inst.op, inst.dest, 0, out.AddConstant(gpr.GetImm(inst.src1) + inst.constant)); @@ -627,6 +628,7 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts case IROp::Load16: case IROp::Load16Ext: case IROp::Load32: + case IROp::Load32Linked: if (gpr.IsImm(inst.src1) && inst.src1 != inst.dest) { gpr.MapDirty(inst.dest); out.Write(inst.op, inst.dest, 0, out.AddConstant(gpr.GetImm(inst.src1) + inst.constant)); @@ -1507,10 +1509,12 @@ bool ApplyMemoryValidation(const IRWriter &in, IRWriter &out, const IROptions &o break; case IROp::Load32: + case IROp::Load32Linked: case IROp::LoadFloat: case IROp::Store32: + case IROp::Store32Conditional: case IROp::StoreFloat: - addValidate(IROp::ValidateAddress32, inst, inst.op == IROp::Store32 || inst.op == IROp::StoreFloat); + addValidate(IROp::ValidateAddress32, inst, inst.op == IROp::Store32 || inst.op == IROp::Store32Conditional || inst.op == IROp::StoreFloat); break; case IROp::LoadVec4: diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h index b5944c3db5..c88c9fe345 100644 --- a/Core/MIPS/JitCommon/JitCommon.h +++ b/Core/MIPS/JitCommon/JitCommon.h @@ -54,6 +54,7 @@ namespace MIPSComp { virtual void Comp_RunBlock(MIPSOpcode op) = 0; virtual void Comp_ReplacementFunc(MIPSOpcode op) = 0; virtual void Comp_ITypeMem(MIPSOpcode op) = 0; + virtual void Comp_StoreSync(MIPSOpcode op) = 0; virtual void Comp_Cache(MIPSOpcode op) = 0; virtual void Comp_RelBranch(MIPSOpcode op) = 0; virtual void Comp_RelBranchRI(MIPSOpcode op) = 0; diff --git a/Core/MIPS/MIPS/MipsJit.h b/Core/MIPS/MIPS/MipsJit.h index 195579b37d..9026ac185c 100644 --- a/Core/MIPS/MIPS/MipsJit.h +++ b/Core/MIPS/MIPS/MipsJit.h @@ -62,6 +62,7 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override {} + void Comp_StoreSync(MIPSOpcode op) override {} void Comp_Cache(MIPSOpcode op) override {} void Comp_RelBranch(MIPSOpcode op) override {} diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 3a102f63f1..f012b0eab4 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -150,7 +150,7 @@ static const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ........ INSTR("swr", JITFUNC(Comp_ITypeMem), Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM|MEMTYPE_WORD), INSTR("cache", JITFUNC(Comp_Cache), Dis_Cache, Int_Cache, IN_MEM|IN_IMM16|IN_RS_ADDR), //48 - INSTR("ll", JITFUNC(Comp_Generic), Dis_Generic, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD), + INSTR("ll", JITFUNC(Comp_StoreSync), Dis_Generic, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD), INSTR("lwc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_FT|MEMTYPE_FLOAT|IS_FPU), INSTR("lv.s", JITFUNC(Comp_SV), Dis_SV, Int_SV, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_FLOAT), INVALID, @@ -159,7 +159,7 @@ static const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ........ INSTR("lv.q", JITFUNC(Comp_SVQ), Dis_SVQ, Int_SVQ, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_VQUAD), //copU ENCODING(VFPU5), //56 - INSTR("sc", JITFUNC(Comp_Generic), Dis_Generic, Int_StoreSync, IN_IMM16|IN_RS_ADDR|IN_OTHER|IN_RT|OUT_RT|OUT_MEM|MEMTYPE_WORD), + INSTR("sc", JITFUNC(Comp_StoreSync), Dis_Generic, Int_StoreSync, IN_IMM16|IN_RS_ADDR|IN_OTHER|IN_RT|OUT_RT|OUT_MEM|MEMTYPE_WORD), INSTR("swc1", JITFUNC(Comp_FPULS), Dis_FPULS, Int_FPULS, IN_IMM16|IN_RS_ADDR|IN_FT|OUT_MEM|MEMTYPE_FLOAT|IS_FPU), //copU INSTR("sv.s", JITFUNC(Comp_SV), Dis_SV, Int_SV, IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_MEM|IS_VFPU|VFPU_NO_PREFIX|MEMTYPE_FLOAT), INVALID, diff --git a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp b/Core/MIPS/RiscV/RiscVCompLoadStore.cpp index a543236610..8cc8af74de 100644 --- a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp +++ b/Core/MIPS/RiscV/RiscVCompLoadStore.cpp @@ -112,6 +112,10 @@ void RiscVJit::CompIR_Load(IRInst inst) { LW(gpr.R(inst.dest), addrReg, imm); break; + case IROp::Load32Linked: + CompIR_Generic(inst); + break; + default: INVALIDOP; break; @@ -249,6 +253,14 @@ void RiscVJit::CompIR_Store(IRInst inst) { } } +void RiscVJit::CompIR_CondStore(IRInst inst) { + CONDITIONAL_DISABLE; + if (inst.op != IROp::Store32Conditional) + INVALIDOP; + + CompIR_Generic(inst); +} + void RiscVJit::CompIR_StoreShift(IRInst inst) { CONDITIONAL_DISABLE; diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp index b94369c4ca..9b8839a4eb 100644 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ b/Core/MIPS/RiscV/RiscVJit.cpp @@ -201,6 +201,7 @@ void RiscVJit::CompileIRInst(IRInst inst) { case IROp::Load16: case IROp::Load16Ext: case IROp::Load32: + case IROp::Load32Linked: CompIR_Load(inst); break; @@ -223,6 +224,10 @@ void RiscVJit::CompileIRInst(IRInst inst) { CompIR_Store(inst); break; + case IROp::Store32Conditional: + CompIR_CondStore(inst); + break; + case IROp::Store32Left: case IROp::Store32Right: CompIR_StoreShift(inst); diff --git a/Core/MIPS/RiscV/RiscVJit.h b/Core/MIPS/RiscV/RiscVJit.h index 02c90c735d..8a05fdb871 100644 --- a/Core/MIPS/RiscV/RiscVJit.h +++ b/Core/MIPS/RiscV/RiscVJit.h @@ -71,6 +71,7 @@ private: void CompIR_Breakpoint(IRInst inst); void CompIR_Compare(IRInst inst); void CompIR_CondAssign(IRInst inst); + void CompIR_CondStore(IRInst inst); void CompIR_Div(IRInst inst); void CompIR_Exit(IRInst inst); void CompIR_ExitIf(IRInst inst); diff --git a/Core/MIPS/fake/FakeJit.h b/Core/MIPS/fake/FakeJit.h index 7fe42a6981..bce7fe92d3 100644 --- a/Core/MIPS/fake/FakeJit.h +++ b/Core/MIPS/fake/FakeJit.h @@ -60,6 +60,7 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override {} + void Comp_StoreSync(MIPSOpcode op) override {} void Comp_Cache(MIPSOpcode op) override {} void Comp_RelBranch(MIPSOpcode op) override {} diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index feb627d3e8..9ef4b0b206 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -405,6 +405,12 @@ namespace MIPSComp { } + void Jit::Comp_StoreSync(MIPSOpcode op) { + CONDITIONAL_DISABLE(LSU); + + DISABLE; + } + void Jit::Comp_Cache(MIPSOpcode op) { CONDITIONAL_DISABLE(LSU); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 2e2f806fd8..0a56cfae5b 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -69,6 +69,7 @@ public: // Ops void Comp_ITypeMem(MIPSOpcode op) override; + void Comp_StoreSync(MIPSOpcode op) override; void Comp_Cache(MIPSOpcode op) override; void Comp_RelBranch(MIPSOpcode op) override;