diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index eb351fdb7..5f806855c 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -203,6 +203,14 @@ if(BUILD_TESTING) set_tests_properties(ray_tracing_miss PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_executable(vector_compare_i16_u16_tests tests/VectorCompareI16U16.cpp) + target_link_libraries(vector_compare_i16_u16_tests PRIVATE shader_recompiler_agc_driver libc) + configure_windows_unwind(vector_compare_i16_u16_tests) + add_test(NAME vector_compare_i16_u16 COMMAND vector_compare_i16_u16_tests) + if(WIN32) + set_tests_properties(vector_compare_i16_u16 PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() target_include_directories(guest_indexed_draw_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(guest_indexed_draw_tests PRIVATE libSceAgc libSceAgcDriver libc) configure_windows_unwind(guest_indexed_draw_tests) diff --git a/core/libs/tests/VectorCompareI16U16.cpp b/core/libs/tests/VectorCompareI16U16.cpp new file mode 100644 index 000000000..63c193b51 --- /dev/null +++ b/core/libs/tests/VectorCompareI16U16.cpp @@ -0,0 +1,32 @@ +#include "Translation/TranslationContext.hpp" +#include "RdnaDecoder/RdnaVectorOpDecoder.hpp" +#include +#include + +using namespace ShaderRecompiler; +static void Require(bool value) { if (!value) throw std::runtime_error("vector compare regression"); } +static void Check(std::uint32_t encoding, RdnaOpcode opcode) { + const std::array code{(encoding << 17u) | (1u << 9u) | 100u}; + const RdnaInstruction instruction = DecodeRdnaVopc(0u, code, 0u); + Require(instruction.op == opcode); + Require(instruction.family == RdnaInstructionFamily::VOPC); + Require(IsVectorAluOpcode(instruction.op)); + Require(instruction.destination.kind == RdnaOperandKind::ExecLo); + IrProgram program; + auto& block = program.CreateBlock(); + program.SetEntryBlock(block); + TranslationContext context(program, block, 256); + context.TranslateInstruction(instruction); +} +int main() { + Check(0x99u, RdnaOpcode::VCmpxLtI16); + Check(0x9au, RdnaOpcode::VCmpxEqI16); + Check(0x9bu, RdnaOpcode::VCmpxLeI16); + Check(0x9cu, RdnaOpcode::VCmpxGtI16); + Check(0x9du, RdnaOpcode::VCmpxNeI16); + Check(0x9eu, RdnaOpcode::VCmpxGeI16); + Check(0xbau, RdnaOpcode::VCmpxEqU16); + Check(0xbbu, RdnaOpcode::VCmpxLeU16); + Check(0xbdu, RdnaOpcode::VCmpxNeU16); + Check(0xbeu, RdnaOpcode::VCmpxGeU16); +} diff --git a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp index a12eaee88..5766be453 100644 --- a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp +++ b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp @@ -394,6 +394,12 @@ enum class RdnaOpcode : std::uint16_t { VCmpGtI16, VCmpNeI16, VCmpGeI16, + VCmpxLtI16, + VCmpxEqI16, + VCmpxLeI16, + VCmpxGtI16, + VCmpxNeI16, + VCmpxGeI16, VCmpLtF16, VCmpEqF16, VCmpLeF16, @@ -420,7 +426,11 @@ enum class RdnaOpcode : std::uint16_t { VCmpLeU16, VCmpGtU16, VCmpxLtU16, + VCmpxEqU16, + VCmpxLeU16, VCmpxGtU16, + VCmpxNeU16, + VCmpxGeU16, VCmpNeU16, VCmpGeU16, VCmpFU32, diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp index 8d5c3e7e2..6b42b406c 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp @@ -367,6 +367,12 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) { case RdnaOpcode::VCmpGtI16: case RdnaOpcode::VCmpNeI16: case RdnaOpcode::VCmpGeI16: + case RdnaOpcode::VCmpxLtI16: + case RdnaOpcode::VCmpxEqI16: + case RdnaOpcode::VCmpxLeI16: + case RdnaOpcode::VCmpxGtI16: + case RdnaOpcode::VCmpxNeI16: + case RdnaOpcode::VCmpxGeI16: case RdnaOpcode::VCmpLtF16: case RdnaOpcode::VCmpEqF16: case RdnaOpcode::VCmpLeF16: @@ -393,7 +399,11 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) { case RdnaOpcode::VCmpLeU16: case RdnaOpcode::VCmpGtU16: case RdnaOpcode::VCmpxLtU16: + case RdnaOpcode::VCmpxEqU16: + case RdnaOpcode::VCmpxLeU16: case RdnaOpcode::VCmpxGtU16: + case RdnaOpcode::VCmpxNeU16: + case RdnaOpcode::VCmpxGeU16: case RdnaOpcode::VCmpNeU16: case RdnaOpcode::VCmpGeU16: case RdnaOpcode::VCmpFU32: diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp index 63161841b..029d6a3cf 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp @@ -258,6 +258,12 @@ constexpr VopcOpcodeInfo vopcOpcodes[] = { {0x95u, RdnaOpcode::VCmpxNeI32}, {0x96u, RdnaOpcode::VCmpxGeI32}, {0x98u, RdnaOpcode::VCmpxClassF32}, + {0x99u, RdnaOpcode::VCmpxLtI16}, + {0x9au, RdnaOpcode::VCmpxEqI16}, + {0x9bu, RdnaOpcode::VCmpxLeI16}, + {0x9cu, RdnaOpcode::VCmpxGtI16}, + {0x9du, RdnaOpcode::VCmpxNeI16}, + {0x9eu, RdnaOpcode::VCmpxGeI16}, {0xa9u, RdnaOpcode::VCmpLtU16}, {0xaau, RdnaOpcode::VCmpEqU16}, {0xabu, RdnaOpcode::VCmpLeU16}, @@ -265,7 +271,11 @@ constexpr VopcOpcodeInfo vopcOpcodes[] = { {0xadu, RdnaOpcode::VCmpNeU16}, {0xaeu, RdnaOpcode::VCmpGeU16}, {0xb9u, RdnaOpcode::VCmpxLtU16, false}, + {0xbau, RdnaOpcode::VCmpxEqU16}, + {0xbbu, RdnaOpcode::VCmpxLeU16}, {0xbcu, RdnaOpcode::VCmpxGtU16}, + {0xbdu, RdnaOpcode::VCmpxNeU16}, + {0xbeu, RdnaOpcode::VCmpxGeU16}, {0xc0u, RdnaOpcode::VCmpFU32}, {0xc1u, RdnaOpcode::VCmpLtU32}, {0xc2u, RdnaOpcode::VCmpEqU32}, @@ -1124,8 +1134,18 @@ bool isVopcCompareExec(RdnaOpcode opcode) { case RdnaOpcode::VCmpxGeU32: case RdnaOpcode::VCmpxNeI64: case RdnaOpcode::VCmpxNeU64: + case RdnaOpcode::VCmpxLtI16: + case RdnaOpcode::VCmpxEqI16: + case RdnaOpcode::VCmpxLeI16: + case RdnaOpcode::VCmpxGtI16: + case RdnaOpcode::VCmpxNeI16: + case RdnaOpcode::VCmpxGeI16: case RdnaOpcode::VCmpxLtU16: + case RdnaOpcode::VCmpxEqU16: + case RdnaOpcode::VCmpxLeU16: case RdnaOpcode::VCmpxGtU16: + case RdnaOpcode::VCmpxNeU16: + case RdnaOpcode::VCmpxGeU16: case RdnaOpcode::VCmpxLtF16: case RdnaOpcode::VCmpxEqF16: case RdnaOpcode::VCmpxLeF16: diff --git a/core/shader/recompiler/Translation/src/VectorInstructions.cpp b/core/shader/recompiler/Translation/src/VectorInstructions.cpp index ff327c922..5fee4be62 100644 --- a/core/shader/recompiler/Translation/src/VectorInstructions.cpp +++ b/core/shader/recompiler/Translation/src/VectorInstructions.cpp @@ -148,15 +148,27 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) { case RdnaOpcode::VCmpEqU16: emitInteger16Compare(inst, IrOpcode::IEqual32, false, false); return true; + case RdnaOpcode::VCmpxEqU16: + emitInteger16Compare(inst, IrOpcode::IEqual32, false, true); + return true; case RdnaOpcode::VCmpEqI16: emitInteger16Compare(inst, IrOpcode::IEqual32, true, false); return true; + case RdnaOpcode::VCmpxEqI16: + emitInteger16Compare(inst, IrOpcode::IEqual32, true, true); + return true; case RdnaOpcode::VCmpNeU16: emitInteger16Compare(inst, IrOpcode::INotEqual32, false, false); return true; + case RdnaOpcode::VCmpxNeU16: + emitInteger16Compare(inst, IrOpcode::INotEqual32, false, true); + return true; case RdnaOpcode::VCmpNeI16: emitInteger16Compare(inst, IrOpcode::INotEqual32, true, false); return true; + case RdnaOpcode::VCmpxNeI16: + emitInteger16Compare(inst, IrOpcode::INotEqual32, true, true); + return true; case RdnaOpcode::VCmpGtU16: emitInteger16Compare(inst, IrOpcode::UGreaterThan32, false, false); return true; @@ -166,6 +178,9 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) { case RdnaOpcode::VCmpGeU16: emitInteger16Compare(inst, IrOpcode::UGreaterThanEqual32, false, false); return true; + case RdnaOpcode::VCmpxGeU16: + emitInteger16Compare(inst, IrOpcode::UGreaterThanEqual32, false, true); + return true; case RdnaOpcode::VCmpLtU16: emitInteger16Compare(inst, IrOpcode::ULessThan32, false, false); return true; @@ -175,18 +190,33 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) { case RdnaOpcode::VCmpLeU16: emitInteger16Compare(inst, IrOpcode::ULessThanEqual32, false, false); return true; + case RdnaOpcode::VCmpxLeU16: + emitInteger16Compare(inst, IrOpcode::ULessThanEqual32, false, true); + return true; case RdnaOpcode::VCmpGtI16: emitInteger16Compare(inst, IrOpcode::SGreaterThan32, true, false); return true; + case RdnaOpcode::VCmpxGtI16: + emitInteger16Compare(inst, IrOpcode::SGreaterThan32, true, true); + return true; case RdnaOpcode::VCmpGeI16: emitInteger16Compare(inst, IrOpcode::SGreaterThanEqual32, true, false); return true; + case RdnaOpcode::VCmpxGeI16: + emitInteger16Compare(inst, IrOpcode::SGreaterThanEqual32, true, true); + return true; case RdnaOpcode::VCmpLtI16: emitInteger16Compare(inst, IrOpcode::SLessThan32, true, false); return true; + case RdnaOpcode::VCmpxLtI16: + emitInteger16Compare(inst, IrOpcode::SLessThan32, true, true); + return true; case RdnaOpcode::VCmpLeI16: emitInteger16Compare(inst, IrOpcode::SLessThanEqual32, true, false); return true; + case RdnaOpcode::VCmpxLeI16: + emitInteger16Compare(inst, IrOpcode::SLessThanEqual32, true, true); + return true; case RdnaOpcode::VCmpEqF32: emitFloatCompare(inst, IrOpcode::FPOrdEqual32, false, false); return true;