mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-19 12:07:02 +02:00
[shader_recompiler] Add IAbs64 to prevent errors when using I2F with a 64-bit packed CBUF variant (#2918)
- Using I2F cbuf variant (packed 32x2 aka. U64) - Code will call IAbs() if some conditions are met (signed + abs bit) - Uh oh we don't have a variant for 64 bits! - Fuck now we just made BAD ir code :( Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2918 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
6a9ad5e1ea
commit
0e6ea2d9d6
10 changed files with 52 additions and 23 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -313,6 +316,7 @@ void EmitUDiv32(EmitContext& ctx, IR::Inst& inst, ScalarU32 a, ScalarU32 b);
|
||||||
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
||||||
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value);
|
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, Register value);
|
||||||
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
||||||
|
void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, ScalarS32 value);
|
||||||
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift);
|
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift);
|
||||||
void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, ScalarU32 shift);
|
void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, ScalarRegister base, ScalarU32 shift);
|
||||||
void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift);
|
void EmitShiftRightLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -113,6 +116,10 @@ void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
|
||||||
ctx.Add("ABS.S {},{};", inst, value);
|
ctx.Add("ABS.S {},{};", inst, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
|
||||||
|
ctx.Add("ABS.S64 {},{};", inst, value);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift) {
|
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, ScalarU32 shift) {
|
||||||
ctx.Add("SHL.U {}.x,{},{};", inst, base, shift);
|
ctx.Add("SHL.U {}.x,{},{};", inst, base, shift);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -373,6 +376,7 @@ void EmitUDiv32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::strin
|
||||||
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
void EmitINeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
||||||
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
void EmitINeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
||||||
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
||||||
|
void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
|
||||||
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
||||||
std::string_view shift);
|
std::string_view shift);
|
||||||
void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
void EmitShiftLeftLogical64(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,11 @@ void EmitIAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
|
||||||
ctx.AddU32("{}=abs(int({}));", inst, value);
|
ctx.AddU32("{}=abs(int({}));", inst, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitIAbs64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
|
||||||
|
// TODO: Uhm, are you sure? This may crash on some drivers!
|
||||||
|
ctx.AddU32("{}=abs(int64_t({}));", inst, value);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
void EmitShiftLeftLogical32(EmitContext& ctx, IR::Inst& inst, std::string_view base,
|
||||||
std::string_view shift) {
|
std::string_view shift) {
|
||||||
ctx.AddU32("{}={}<<{};", inst, base, shift);
|
ctx.AddU32("{}={}<<{};", inst, base, shift);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -293,6 +296,7 @@ Id EmitUDiv32(EmitContext& ctx, Id a, Id b);
|
||||||
Id EmitINeg32(EmitContext& ctx, Id value);
|
Id EmitINeg32(EmitContext& ctx, Id value);
|
||||||
Id EmitINeg64(EmitContext& ctx, Id value);
|
Id EmitINeg64(EmitContext& ctx, Id value);
|
||||||
Id EmitIAbs32(EmitContext& ctx, Id value);
|
Id EmitIAbs32(EmitContext& ctx, Id value);
|
||||||
|
Id EmitIAbs64(EmitContext& ctx, Id value);
|
||||||
Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift);
|
Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift);
|
||||||
Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift);
|
Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift);
|
||||||
Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift);
|
Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift);
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,10 @@ Id EmitIAbs32(EmitContext& ctx, Id value) {
|
||||||
return ctx.OpSAbs(ctx.U32[1], value);
|
return ctx.OpSAbs(ctx.U32[1], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id EmitIAbs64(EmitContext& ctx, Id value) {
|
||||||
|
return ctx.OpSAbs(ctx.U64, value);
|
||||||
|
}
|
||||||
|
|
||||||
Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) {
|
Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) {
|
||||||
return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift);
|
return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1190,8 +1190,15 @@ U32U64 IREmitter::INeg(const U32U64& value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 IREmitter::IAbs(const U32& value) {
|
U32U64 IREmitter::IAbs(const U32U64& value) {
|
||||||
return Inst<U32>(Opcode::IAbs32, value);
|
switch (value.Type()) {
|
||||||
|
case Type::U32:
|
||||||
|
return Inst<U32>(Opcode::IAbs32, value);
|
||||||
|
case Type::U64:
|
||||||
|
return Inst<U64>(Opcode::IAbs64, value);
|
||||||
|
default:
|
||||||
|
ThrowInvalidType(value.Type());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) {
|
U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -218,7 +221,7 @@ public:
|
||||||
[[nodiscard]] U32 IMul(const U32& a, const U32& b);
|
[[nodiscard]] U32 IMul(const U32& a, const U32& b);
|
||||||
[[nodiscard]] U32 IDiv(const U32& a, const U32& b, bool is_signed = false);
|
[[nodiscard]] U32 IDiv(const U32& a, const U32& b, bool is_signed = false);
|
||||||
[[nodiscard]] U32U64 INeg(const U32U64& value);
|
[[nodiscard]] U32U64 INeg(const U32U64& value);
|
||||||
[[nodiscard]] U32 IAbs(const U32& value);
|
[[nodiscard]] U32U64 IAbs(const U32U64& value);
|
||||||
[[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift);
|
[[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift);
|
||||||
[[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift);
|
[[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift);
|
||||||
[[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift);
|
[[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift);
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,7 @@ OPCODE(UDiv32, U32, U32,
|
||||||
OPCODE(INeg32, U32, U32, )
|
OPCODE(INeg32, U32, U32, )
|
||||||
OPCODE(INeg64, U64, U64, )
|
OPCODE(INeg64, U64, U64, )
|
||||||
OPCODE(IAbs32, U32, U32, )
|
OPCODE(IAbs32, U32, U32, )
|
||||||
|
OPCODE(IAbs64, U64, U64, )
|
||||||
OPCODE(ShiftLeftLogical32, U32, U32, U32, )
|
OPCODE(ShiftLeftLogical32, U32, U32, U32, )
|
||||||
OPCODE(ShiftLeftLogical64, U64, U64, U32, )
|
OPCODE(ShiftLeftLogical64, U64, U64, U32, )
|
||||||
OPCODE(ShiftRightLogical32, U32, U32, U32, )
|
OPCODE(ShiftRightLogical32, U32, U32, U32, )
|
||||||
|
|
|
||||||
|
|
@ -70,32 +70,25 @@ void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
|
||||||
int src_bitsize{};
|
int src_bitsize{};
|
||||||
switch (i2f.int_format) {
|
switch (i2f.int_format) {
|
||||||
case IntFormat::U8:
|
case IntFormat::U8:
|
||||||
src = v.ir.BitFieldExtract(src, v.ir.Imm32(static_cast<u32>(i2f.selector) * 8),
|
src = v.ir.BitFieldExtract(src, v.ir.Imm32(u32(i2f.selector) * 8), v.ir.Imm32(8), is_signed);
|
||||||
v.ir.Imm32(8), is_signed);
|
if (i2f.abs != 0)
|
||||||
if (i2f.abs != 0) {
|
|
||||||
src = SmallAbs(v, src, 8);
|
src = SmallAbs(v, src, 8);
|
||||||
}
|
|
||||||
src_bitsize = 8;
|
src_bitsize = 8;
|
||||||
break;
|
break;
|
||||||
case IntFormat::U16:
|
case IntFormat::U16:
|
||||||
if (i2f.selector == 1 || i2f.selector == 3) {
|
if (i2f.selector == 1 || i2f.selector == 3)
|
||||||
throw NotImplementedException("Invalid U16 selector {}", i2f.selector.Value());
|
throw NotImplementedException("Invalid U16 selector {}", i2f.selector.Value());
|
||||||
}
|
src = v.ir.BitFieldExtract(src, v.ir.Imm32(u32(i2f.selector) * 8), v.ir.Imm32(16), is_signed);
|
||||||
src = v.ir.BitFieldExtract(src, v.ir.Imm32(static_cast<u32>(i2f.selector) * 8),
|
if (i2f.abs != 0)
|
||||||
v.ir.Imm32(16), is_signed);
|
|
||||||
if (i2f.abs != 0) {
|
|
||||||
src = SmallAbs(v, src, 16);
|
src = SmallAbs(v, src, 16);
|
||||||
}
|
|
||||||
src_bitsize = 16;
|
src_bitsize = 16;
|
||||||
break;
|
break;
|
||||||
case IntFormat::U32:
|
case IntFormat::U32:
|
||||||
case IntFormat::U64:
|
case IntFormat::U64:
|
||||||
if (i2f.selector != 0) {
|
if (i2f.selector != 0)
|
||||||
throw NotImplementedException("Unexpected selector {}", i2f.selector.Value());
|
throw NotImplementedException("Unexpected selector {}", i2f.selector.Value());
|
||||||
}
|
if (i2f.abs != 0 && is_signed)
|
||||||
if (i2f.abs != 0 && is_signed) {
|
|
||||||
src = v.ir.IAbs(src);
|
src = v.ir.IAbs(src);
|
||||||
}
|
|
||||||
src_bitsize = i2f.int_format == IntFormat::U64 ? 64 : 32;
|
src_bitsize = i2f.int_format == IntFormat::U64 ? 64 : 32;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -106,9 +99,7 @@ void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
|
||||||
.rounding = CastFpRounding(i2f.fp_rounding),
|
.rounding = CastFpRounding(i2f.fp_rounding),
|
||||||
.fmz_mode = IR::FmzMode::DontCare,
|
.fmz_mode = IR::FmzMode::DontCare,
|
||||||
};
|
};
|
||||||
auto value{v.ir.ConvertIToF(static_cast<size_t>(dst_bitsize),
|
auto value{v.ir.ConvertIToF(size_t(dst_bitsize), size_t(conversion_src_bitsize), is_signed, src, fp_control)};
|
||||||
static_cast<size_t>(conversion_src_bitsize), is_signed, src,
|
|
||||||
fp_control)};
|
|
||||||
if (i2f.neg != 0) {
|
if (i2f.neg != 0) {
|
||||||
if (i2f.abs != 0 || !is_signed) {
|
if (i2f.abs != 0 || !is_signed) {
|
||||||
// We know the value is positive
|
// We know the value is positive
|
||||||
|
|
@ -141,9 +132,8 @@ void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
|
||||||
throw NotImplementedException("Unaligned destination {}", i2f.dest_reg.Value());
|
throw NotImplementedException("Unaligned destination {}", i2f.dest_reg.Value());
|
||||||
}
|
}
|
||||||
const IR::Value vector{v.ir.UnpackDouble2x32(value)};
|
const IR::Value vector{v.ir.UnpackDouble2x32(value)};
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i)
|
||||||
v.X(i2f.dest_reg + i, IR::U32{v.ir.CompositeExtract(vector, static_cast<size_t>(i))});
|
v.X(i2f.dest_reg + i, IR::U32{v.ir.CompositeExtract(vector, size_t(i))});
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue