mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-20 19:44:46 +00:00
General fixes
This commit is contained in:
parent
20c4e07049
commit
71a1c55feb
9 changed files with 67 additions and 37 deletions
|
@ -12,16 +12,15 @@ using namespace Xbyak::util;
|
|||
|
||||
void EmitGetUserData(EmitContext& ctx, const Operands& dest, IR::ScalarReg reg) {
|
||||
const u32 offset = static_cast<u32>(reg) << 2;
|
||||
Reg& tmp = ctx.TempGPReg();
|
||||
Reg tmp = ctx.TempGPReg();
|
||||
ctx.Code().lea(tmp, ptr[ctx.UserData() + offset]);
|
||||
MovGP( ctx, dest[0], dword[tmp]);
|
||||
}
|
||||
|
||||
void EmitSetUserData(EmitContext& ctx, const Operands& offset, const Operands& value) {
|
||||
Reg& tmp = ctx.TempGPReg();
|
||||
Reg tmp = ctx.TempGPReg();
|
||||
MovGP(ctx, tmp, offset[0]);
|
||||
ctx.Code().shl(tmp, 2);
|
||||
ctx.Code().lea(tmp, ptr[ctx.UserData() + tmp]);
|
||||
ctx.Code().lea(tmp, ptr[ctx.UserData() + tmp * 4]);
|
||||
MovGP(ctx, dword[tmp], value[0]);
|
||||
}
|
||||
|
||||
|
@ -58,32 +57,53 @@ void EmitGetGotoVariable(EmitContext&) {
|
|||
}
|
||||
|
||||
void EmitReadConst(EmitContext& ctx, const Operands& dest, const Operands& base, const Operands& offset) {
|
||||
Reg& tmp = ctx.TempGPReg();
|
||||
Reg tmp = dest[0].IsMem() ? ctx.TempGPReg() : dest[0].Reg().changeBit(64);
|
||||
Reg off_tmp = offset[0].IsMem() ? ctx.TempGPReg() : offset[0].Reg().changeBit(64);
|
||||
MovGP(ctx, tmp, base[1]);
|
||||
MovGP(ctx, off_tmp, offset[0]);
|
||||
ctx.Code().shl(tmp, 32);
|
||||
ctx.Code().or_(tmp, base[0].Op());
|
||||
if (offset[0].IsMem()) {
|
||||
ctx.Code().add(tmp, offset[0].Mem());
|
||||
} else {
|
||||
ctx.Code().lea(tmp, ptr[tmp + offset[0].Reg().cvt64()]);
|
||||
}
|
||||
ctx.Code().lea(tmp, ptr[tmp + off_tmp * 4]);
|
||||
MovGP(ctx, dest[0], dword[tmp]);
|
||||
}
|
||||
|
||||
void EmitReadConstBuffer(EmitContext& ctx) {
|
||||
throw NotImplementedException("ReadConstBuffer");
|
||||
void EmitReadConstBuffer(EmitContext& ctx, const Operands& dest, const Operands& handle, const Operands& offset) {
|
||||
Reg tmp = dest[0].IsMem() ? ctx.TempGPReg() : dest[0].Reg().changeBit(64);
|
||||
// Reconstruct base address
|
||||
Reg off_tmp = ctx.TempGPReg();
|
||||
MovGP(ctx, tmp, handle[1]);
|
||||
ctx.Code().and_(tmp, 0xFFF);
|
||||
ctx.Code().shl(tmp, 32);
|
||||
MovGP(ctx, off_tmp.cvt32(), handle[0]);
|
||||
ctx.Code().and_(off_tmp.cvt32(), 0xFFFFFFFF);
|
||||
ctx.Code().or_(tmp, off_tmp);
|
||||
// TODO: we should correctly clamp the offset
|
||||
MovGP(ctx, off_tmp, offset[0]);
|
||||
ctx.Code().lea(tmp, ptr[tmp + off_tmp * 4]);
|
||||
MovGP(ctx, dest[0], dword[tmp]);
|
||||
|
||||
}
|
||||
|
||||
void EmitReadStepRate(EmitContext& ctx) {
|
||||
throw NotImplementedException("ReadStepRate");
|
||||
}
|
||||
|
||||
void EmitGetAttribute(EmitContext& ctx) {
|
||||
throw NotImplementedException("GetAttribute");
|
||||
void EmitGetAttribute(EmitContext& ctx, const Operands& dest) {
|
||||
LOG_WARNING(Render_Recompiler, "GetAttribute stubbed, setting to 0.0");
|
||||
if (dest[0].IsMem()) {
|
||||
ctx.Code().mov(dest[0].Mem(), 0);
|
||||
} else {
|
||||
ctx.Code().pxor(dest[0].Xmm(), dest[0].Xmm());
|
||||
}
|
||||
}
|
||||
|
||||
void EmitGetAttributeU32(EmitContext& ctx) {
|
||||
throw NotImplementedException("GetAttributeU32");
|
||||
void EmitGetAttributeU32(EmitContext& ctx, const Operands& dest) {
|
||||
LOG_WARNING(Render_Recompiler, "GetAttributeU32 stubbed, setting to 0");
|
||||
if (dest[0].IsMem()) {
|
||||
ctx.Code().mov(dest[0].Mem(), 0);
|
||||
} else {
|
||||
ctx.Code().xor_(dest[0].Reg(), dest[0].Reg());
|
||||
}
|
||||
}
|
||||
|
||||
void EmitSetAttribute(EmitContext& ctx) {
|
||||
|
|
|
@ -61,7 +61,7 @@ void EmitSetGotoVariable(EmitContext& ctx);
|
|||
void EmitGetGotoVariable(EmitContext& ctx);
|
||||
void EmitSetScc(EmitContext& ctx);
|
||||
void EmitReadConst(EmitContext& ctx, const Operands& dest, const Operands& base, const Operands& offset);
|
||||
void EmitReadConstBuffer(EmitContext& ctx);
|
||||
void EmitReadConstBuffer(EmitContext& ctx, const Operands& dest, const Operands& handle, const Operands& offset);
|
||||
void EmitLoadBufferU8(EmitContext& ctx);
|
||||
void EmitLoadBufferU16(EmitContext& ctx);
|
||||
void EmitLoadBufferU32(EmitContext& ctx);
|
||||
|
@ -95,8 +95,8 @@ void EmitBufferAtomicAnd32(EmitContext& ctx);
|
|||
void EmitBufferAtomicOr32(EmitContext& ctx);
|
||||
void EmitBufferAtomicXor32(EmitContext& ctx);
|
||||
void EmitBufferAtomicSwap32(EmitContext& ctx);
|
||||
void EmitGetAttribute(EmitContext& ctx);
|
||||
void EmitGetAttributeU32(EmitContext& ctx);
|
||||
void EmitGetAttribute(EmitContext& ctx, const Operands& dest);
|
||||
void EmitGetAttributeU32(EmitContext& ctx, const Operands& dest);
|
||||
void EmitSetAttribute(EmitContext& ctx);
|
||||
void EmitGetTessGenericAttribute(EmitContext& ctx);
|
||||
void EmitSetTcsGenericAttribute(EmitContext& ctx);
|
||||
|
|
|
@ -10,29 +10,33 @@ using namespace Xbyak;
|
|||
using namespace Xbyak::util;
|
||||
|
||||
void EmitLogicalOr(EmitContext& ctx, const Operands& dest, const Operands& op1, const Operands& op2) {
|
||||
Reg tmp = dest[0].IsMem() ? ctx.TempGPReg().cvt8() : dest[0].Reg().cvt8();
|
||||
OperandHolder tmp = op2[0].IsMem() && dest[0].IsMem() ? ctx.TempGPReg().cvt8() : dest[0];
|
||||
MovGP(ctx, tmp, op1[0]);
|
||||
ctx.Code().or_(tmp, op2[0].Op());
|
||||
ctx.Code().or_(tmp.Op(), op2[0].Op());
|
||||
ctx.Code().and_(tmp.Op(), 1);
|
||||
MovGP(ctx, dest[0], tmp);
|
||||
}
|
||||
|
||||
void EmitLogicalAnd(EmitContext& ctx, const Operands& dest, const Operands& op1, const Operands& op2) {
|
||||
Reg tmp = dest[0].IsMem() ? ctx.TempGPReg().cvt8() : dest[0].Reg().cvt8();
|
||||
MovGP(ctx, tmp, op1[0]);
|
||||
ctx.Code().and_(tmp, op2[0].Op());
|
||||
OperandHolder tmp = op2[0].IsMem() && dest[0].IsMem() ? ctx.TempGPReg().cvt8() : dest[0];
|
||||
MovGP(ctx, tmp.Op(), op1[0]);
|
||||
ctx.Code().and_(tmp.Op(), op2[0].Op());
|
||||
ctx.Code().and_(tmp.Op(), 1);
|
||||
MovGP(ctx, dest[0], tmp);
|
||||
}
|
||||
|
||||
void EmitLogicalXor(EmitContext& ctx, const Operands& dest, const Operands& op1, const Operands& op2) {
|
||||
Reg tmp = dest[0].IsMem() ? ctx.TempGPReg().cvt8() : dest[0].Reg().cvt8();
|
||||
OperandHolder tmp = op2[0].IsMem() && dest[0].IsMem() ? ctx.TempGPReg().cvt8() : dest[0];
|
||||
MovGP(ctx, tmp, op1[0]);
|
||||
ctx.Code().xor_(tmp, op2[0].Op());
|
||||
ctx.Code().xor_(tmp.Op(), op2[0].Op());
|
||||
ctx.Code().and_(tmp.Op(), 1);
|
||||
MovGP(ctx, dest[0], tmp);
|
||||
}
|
||||
|
||||
void EmitLogicalNot(EmitContext& ctx, const Operands& dest, const Operands& op) {
|
||||
MovGP(ctx, dest[0], op[0]);
|
||||
ctx.Code().not_(dest[0].Op());
|
||||
ctx.Code().and_(dest[0].Op(), 1);
|
||||
}
|
||||
|
||||
} // namespace Shader::Backend::X64
|
|
@ -27,7 +27,8 @@ Reg64& EmitContext::TempGPReg(bool reserve) {
|
|||
if (idx > num_scratch_gp_regs &&
|
||||
std::ranges::find(preserved_regs, reg) == preserved_regs.end()) {
|
||||
preserved_regs.push_back(reg);
|
||||
code.push(reg);
|
||||
code.sub(rsp, 8);
|
||||
code.mov(ptr[rsp], reg);
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
@ -154,7 +155,8 @@ void EmitContext::Epilogue() {
|
|||
code.movups(reg.cvt128(), ptr[rsp]);
|
||||
code.add(rsp, 16);
|
||||
} else {
|
||||
code.pop(reg);
|
||||
code.mov(reg, ptr[rsp]);
|
||||
code.add(rsp, 8);
|
||||
}
|
||||
}
|
||||
preserved_regs.clear();
|
||||
|
|
|
@ -157,13 +157,15 @@ void MovGP(EmitContext& ctx, const OperandHolder& dst, const OperandHolder& src)
|
|||
const u32 dst_bit = dst.Op().getBit();
|
||||
OperandHolder tmp = is_mem2mem ? ctx.TempGPReg(false).changeBit(dst_bit) : dst;
|
||||
if (src_bit < dst_bit) {
|
||||
if (!dst.IsMem() && !src.Op().isBit(32)) {
|
||||
if (!tmp.IsMem() && !src.Op().isBit(32)) {
|
||||
c.movzx(tmp.Reg(), src.Op());
|
||||
} else if (tmp.IsMem()) {
|
||||
Address addr = tmp.Mem();
|
||||
c.mov(addr, 0);
|
||||
addr.setBit(dst_bit);
|
||||
c.mov(addr, src.Reg());
|
||||
} else {
|
||||
if (dst.IsMem()) {
|
||||
c.mov(tmp.Op(), 0);
|
||||
}
|
||||
c.mov(tmp.Op(), src.Op());
|
||||
c.mov(tmp.Reg().cvt32(), src.Op());
|
||||
}
|
||||
} else if (src_bit > dst_bit) {
|
||||
OperandHolder src_tmp = src;
|
||||
|
|
|
@ -46,7 +46,7 @@ void Translator::S_LOAD_DWORD(int num_dwords, const GcnInst& inst) {
|
|||
if (smrd.offset == SQ_SRC_LITERAL) {
|
||||
return ir.Imm32(inst.src[1].code);
|
||||
}
|
||||
return ir.GetScalarReg(IR::ScalarReg(smrd.offset));
|
||||
return ir.ShiftRightLogical(ir.GetScalarReg(IR::ScalarReg(smrd.offset)), ir.Imm32(2));
|
||||
}();
|
||||
const IR::ScalarReg sbase{inst.src[0].code * 2};
|
||||
const IR::Value base =
|
||||
|
|
|
@ -255,8 +255,9 @@ struct Info {
|
|||
std::memcpy(flattened_ud_buf.data(), user_data.data(), user_data.size_bytes());
|
||||
// Run the JIT program to walk the SRT and write the leaves to a flat buffer
|
||||
if (srt_info.walker_func) {
|
||||
srt_info.walker_func(user_data.data(), flattened_ud_buf.data());
|
||||
srt_info.walker_func(flattened_ud_buf.data());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ReadTessConstantBuffer(TessellationDataConstantBuffer& tess_constants) const {
|
||||
|
|
|
@ -244,7 +244,8 @@ SharpLocation TrackSharp(const IR::Inst* inst, const Shader::Info& info) {
|
|||
}
|
||||
return std::nullopt;
|
||||
};
|
||||
// We are not accounting for modifications to after the source.
|
||||
// Value may be modified between the ReadConst/GetUserData and inst.
|
||||
// We don't take this into account.
|
||||
const auto result = IR::BreadthFirstSearch(inst, pred);
|
||||
ASSERT_MSG(result, "Unable to track sharp source");
|
||||
inst = result.value();
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
namespace Shader {
|
||||
|
||||
using PFN_SrtWalker = void PS4_SYSV_ABI (*)(const u32* /*user_data*/, u32* /*flat_dst*/);
|
||||
using PFN_SrtWalker = void PS4_SYSV_ABI (*)(u32* /*flat_dst*/);
|
||||
|
||||
struct PersistentSrtInfo {
|
||||
// Special case when fetch shader uses step rates.
|
||||
|
|
Loading…
Add table
Reference in a new issue