General fixes

This commit is contained in:
Lander Gallastegi 2025-04-10 01:35:24 +02:00
parent 20c4e07049
commit 71a1c55feb
9 changed files with 67 additions and 37 deletions

View File

@ -12,16 +12,15 @@ using namespace Xbyak::util;
void EmitGetUserData(EmitContext& ctx, const Operands& dest, IR::ScalarReg reg) { void EmitGetUserData(EmitContext& ctx, const Operands& dest, IR::ScalarReg reg) {
const u32 offset = static_cast<u32>(reg) << 2; const u32 offset = static_cast<u32>(reg) << 2;
Reg& tmp = ctx.TempGPReg(); Reg tmp = ctx.TempGPReg();
ctx.Code().lea(tmp, ptr[ctx.UserData() + offset]); ctx.Code().lea(tmp, ptr[ctx.UserData() + offset]);
MovGP( ctx, dest[0], dword[tmp]); MovGP( ctx, dest[0], dword[tmp]);
} }
void EmitSetUserData(EmitContext& ctx, const Operands& offset, const Operands& value) { void EmitSetUserData(EmitContext& ctx, const Operands& offset, const Operands& value) {
Reg& tmp = ctx.TempGPReg(); Reg tmp = ctx.TempGPReg();
MovGP(ctx, tmp, offset[0]); MovGP(ctx, tmp, offset[0]);
ctx.Code().shl(tmp, 2); ctx.Code().lea(tmp, ptr[ctx.UserData() + tmp * 4]);
ctx.Code().lea(tmp, ptr[ctx.UserData() + tmp]);
MovGP(ctx, dword[tmp], value[0]); 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) { 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, tmp, base[1]);
MovGP(ctx, off_tmp, offset[0]);
ctx.Code().shl(tmp, 32); ctx.Code().shl(tmp, 32);
ctx.Code().or_(tmp, base[0].Op()); ctx.Code().or_(tmp, base[0].Op());
if (offset[0].IsMem()) { ctx.Code().lea(tmp, ptr[tmp + off_tmp * 4]);
ctx.Code().add(tmp, offset[0].Mem());
} else {
ctx.Code().lea(tmp, ptr[tmp + offset[0].Reg().cvt64()]);
}
MovGP(ctx, dest[0], dword[tmp]); MovGP(ctx, dest[0], dword[tmp]);
} }
void EmitReadConstBuffer(EmitContext& ctx) { void EmitReadConstBuffer(EmitContext& ctx, const Operands& dest, const Operands& handle, const Operands& offset) {
throw NotImplementedException("ReadConstBuffer"); 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) { void EmitReadStepRate(EmitContext& ctx) {
throw NotImplementedException("ReadStepRate"); throw NotImplementedException("ReadStepRate");
} }
void EmitGetAttribute(EmitContext& ctx) { void EmitGetAttribute(EmitContext& ctx, const Operands& dest) {
throw NotImplementedException("GetAttribute"); 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) { void EmitGetAttributeU32(EmitContext& ctx, const Operands& dest) {
throw NotImplementedException("GetAttributeU32"); 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) { void EmitSetAttribute(EmitContext& ctx) {

View File

@ -61,7 +61,7 @@ void EmitSetGotoVariable(EmitContext& ctx);
void EmitGetGotoVariable(EmitContext& ctx); void EmitGetGotoVariable(EmitContext& ctx);
void EmitSetScc(EmitContext& ctx); void EmitSetScc(EmitContext& ctx);
void EmitReadConst(EmitContext& ctx, const Operands& dest, const Operands& base, const Operands& offset); 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 EmitLoadBufferU8(EmitContext& ctx);
void EmitLoadBufferU16(EmitContext& ctx); void EmitLoadBufferU16(EmitContext& ctx);
void EmitLoadBufferU32(EmitContext& ctx); void EmitLoadBufferU32(EmitContext& ctx);
@ -95,8 +95,8 @@ void EmitBufferAtomicAnd32(EmitContext& ctx);
void EmitBufferAtomicOr32(EmitContext& ctx); void EmitBufferAtomicOr32(EmitContext& ctx);
void EmitBufferAtomicXor32(EmitContext& ctx); void EmitBufferAtomicXor32(EmitContext& ctx);
void EmitBufferAtomicSwap32(EmitContext& ctx); void EmitBufferAtomicSwap32(EmitContext& ctx);
void EmitGetAttribute(EmitContext& ctx); void EmitGetAttribute(EmitContext& ctx, const Operands& dest);
void EmitGetAttributeU32(EmitContext& ctx); void EmitGetAttributeU32(EmitContext& ctx, const Operands& dest);
void EmitSetAttribute(EmitContext& ctx); void EmitSetAttribute(EmitContext& ctx);
void EmitGetTessGenericAttribute(EmitContext& ctx); void EmitGetTessGenericAttribute(EmitContext& ctx);
void EmitSetTcsGenericAttribute(EmitContext& ctx); void EmitSetTcsGenericAttribute(EmitContext& ctx);

View File

@ -10,29 +10,33 @@ using namespace Xbyak;
using namespace Xbyak::util; using namespace Xbyak::util;
void EmitLogicalOr(EmitContext& ctx, const Operands& dest, const Operands& op1, const Operands& op2) { 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]); 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); MovGP(ctx, dest[0], tmp);
} }
void EmitLogicalAnd(EmitContext& ctx, const Operands& dest, const Operands& op1, const Operands& op2) { 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(); OperandHolder tmp = op2[0].IsMem() && dest[0].IsMem() ? ctx.TempGPReg().cvt8() : dest[0];
MovGP(ctx, tmp, op1[0]); MovGP(ctx, tmp.Op(), op1[0]);
ctx.Code().and_(tmp, op2[0].Op()); ctx.Code().and_(tmp.Op(), op2[0].Op());
ctx.Code().and_(tmp.Op(), 1);
MovGP(ctx, dest[0], tmp); MovGP(ctx, dest[0], tmp);
} }
void EmitLogicalXor(EmitContext& ctx, const Operands& dest, const Operands& op1, const Operands& op2) { 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]); 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); MovGP(ctx, dest[0], tmp);
} }
void EmitLogicalNot(EmitContext& ctx, const Operands& dest, const Operands& op) { void EmitLogicalNot(EmitContext& ctx, const Operands& dest, const Operands& op) {
MovGP(ctx, dest[0], op[0]); MovGP(ctx, dest[0], op[0]);
ctx.Code().not_(dest[0].Op()); ctx.Code().not_(dest[0].Op());
ctx.Code().and_(dest[0].Op(), 1);
} }
} // namespace Shader::Backend::X64 } // namespace Shader::Backend::X64

View File

@ -27,7 +27,8 @@ Reg64& EmitContext::TempGPReg(bool reserve) {
if (idx > num_scratch_gp_regs && if (idx > num_scratch_gp_regs &&
std::ranges::find(preserved_regs, reg) == preserved_regs.end()) { std::ranges::find(preserved_regs, reg) == preserved_regs.end()) {
preserved_regs.push_back(reg); preserved_regs.push_back(reg);
code.push(reg); code.sub(rsp, 8);
code.mov(ptr[rsp], reg);
} }
return reg; return reg;
} }
@ -154,7 +155,8 @@ void EmitContext::Epilogue() {
code.movups(reg.cvt128(), ptr[rsp]); code.movups(reg.cvt128(), ptr[rsp]);
code.add(rsp, 16); code.add(rsp, 16);
} else { } else {
code.pop(reg); code.mov(reg, ptr[rsp]);
code.add(rsp, 8);
} }
} }
preserved_regs.clear(); preserved_regs.clear();

View File

@ -157,13 +157,15 @@ void MovGP(EmitContext& ctx, const OperandHolder& dst, const OperandHolder& src)
const u32 dst_bit = dst.Op().getBit(); const u32 dst_bit = dst.Op().getBit();
OperandHolder tmp = is_mem2mem ? ctx.TempGPReg(false).changeBit(dst_bit) : dst; OperandHolder tmp = is_mem2mem ? ctx.TempGPReg(false).changeBit(dst_bit) : dst;
if (src_bit < dst_bit) { 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()); 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 { } else {
if (dst.IsMem()) { c.mov(tmp.Reg().cvt32(), src.Op());
c.mov(tmp.Op(), 0);
}
c.mov(tmp.Op(), src.Op());
} }
} else if (src_bit > dst_bit) { } else if (src_bit > dst_bit) {
OperandHolder src_tmp = src; OperandHolder src_tmp = src;

View File

@ -46,7 +46,7 @@ void Translator::S_LOAD_DWORD(int num_dwords, const GcnInst& inst) {
if (smrd.offset == SQ_SRC_LITERAL) { if (smrd.offset == SQ_SRC_LITERAL) {
return ir.Imm32(inst.src[1].code); 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::ScalarReg sbase{inst.src[0].code * 2};
const IR::Value base = const IR::Value base =

View File

@ -255,8 +255,9 @@ struct Info {
std::memcpy(flattened_ud_buf.data(), user_data.data(), user_data.size_bytes()); 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 // Run the JIT program to walk the SRT and write the leaves to a flat buffer
if (srt_info.walker_func) { 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 { void ReadTessConstantBuffer(TessellationDataConstantBuffer& tess_constants) const {

View File

@ -244,7 +244,8 @@ SharpLocation TrackSharp(const IR::Inst* inst, const Shader::Info& info) {
} }
return std::nullopt; 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); const auto result = IR::BreadthFirstSearch(inst, pred);
ASSERT_MSG(result, "Unable to track sharp source"); ASSERT_MSG(result, "Unable to track sharp source");
inst = result.value(); inst = result.value();

View File

@ -9,7 +9,7 @@
namespace Shader { 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 { struct PersistentSrtInfo {
// Special case when fetch shader uses step rates. // Special case when fetch shader uses step rates.