rsx/asm: Add support for more opcodes and add tests for mixed block IO

This commit is contained in:
kd-11 2025-11-30 23:14:40 +03:00 committed by kd-11
parent 13d66f324b
commit ed397c5d67
2 changed files with 61 additions and 29 deletions

View file

@ -8,6 +8,32 @@
namespace rsx::assembler
{
static std::unordered_map<std::string, FP_opcode> s_opcode_lookup
{
// Arithmetic
{ "NOP", RSX_FP_OPCODE_NOP },
{ "MOV", RSX_FP_OPCODE_MOV },
{ "ADD", RSX_FP_OPCODE_ADD },
{ "MAD", RSX_FP_OPCODE_MAD },
{ "FMA", RSX_FP_OPCODE_MAD },
{ "DP3", RSX_FP_OPCODE_DP3 },
{ "DP4", RSX_FP_OPCODE_DP4 },
// Pack-unpack operations are great for testing dependencies
{ "PKH", RSX_FP_OPCODE_PK2 },
{ "UPH", RSX_FP_OPCODE_UP2 },
{ "PK16U", RSX_FP_OPCODE_PK16 },
{ "UP16U", RSX_FP_OPCODE_UP16 },
{ "PK8U", RSX_FP_OPCODE_PKB },
{ "UP8U", RSX_FP_OPCODE_UPB },
{ "PK8G", RSX_FP_OPCODE_PKG },
{ "UP8G", RSX_FP_OPCODE_UPG },
{ "PK8S", RSX_FP_OPCODE_PK4 },
{ "UP8S", RSX_FP_OPCODE_UP4 },
// TODO: Add more
};
Instruction* FPIR::load(const RegisterRef& ref, int operand, Instruction* prev)
{
Instruction* target = prev;
@ -233,39 +259,15 @@ namespace rsx::assembler
inst->bytecode[1] = s0.HEX; \
} while (0)
if (op == "MOV")
const auto found = s_opcode_lookup.find(op);
if (found == s_opcode_lookup.end())
{
SET_OPCODE(RSX_FP_OPCODE_MOV);
return;
fmt::throw_exception("Unhandled instruction '%s'", op);
}
if (op == "ADD")
{
SET_OPCODE(RSX_FP_OPCODE_ADD);
return;
}
if (op == "MAD" || op == "FMA")
{
SET_OPCODE(RSX_FP_OPCODE_MAD);
return;
}
if (op == "UP4S")
{
SET_OPCODE(RSX_FP_OPCODE_UP4);
return;
}
if (op == "PK4S")
{
SET_OPCODE(RSX_FP_OPCODE_PK4);
return;
}
SET_OPCODE(found->second);
#undef SET_OPCODE
fmt::throw_exception("Unhandled instruction '%s'", op);
};
std::string op, dst;

View file

@ -74,7 +74,7 @@ namespace rsx::assembler
TEST(TestFPIR, RegisterAnnotationPass)
{
// Code snippet reads from R0 and R2, clobbers R0, R1, H0
// Code snippet reads from R0, R1 and H4, clobbers R1, H0
auto graph = CFG_from_source(R"(
ADD R1, R0, R1;
MOV H0, H4;
@ -99,4 +99,34 @@ namespace rsx::assembler
EXPECT_EQ(block.input_list[1].reg, R0);
EXPECT_EQ(block.input_list[2].reg, R1);
}
TEST(TestFPIR, RegisterAnnotationPass_MixedIO)
{
// Code snippet reads from R0, R1, clobbers R0, R1, H0.
// The H2 read does not count because R1 is clobbered.
auto graph = CFG_from_source(R"(
ADD R1, R0, R1;
PK8U R0, R1;
MOV H0, H2;
)");
ASSERT_EQ(graph.blocks.size(), 1);
ASSERT_EQ(graph.blocks.front().instructions.size(), 3);
auto& block = graph.blocks.front();
RSXFragmentProgram prog{};
FP::RegisterAnnotationPass annotation_pass(prog);
annotation_pass.run(graph);
ASSERT_EQ(block.clobber_list.size(), 3);
ASSERT_EQ(block.input_list.size(), 2);
EXPECT_EQ(block.clobber_list[0].reg, H0);
EXPECT_EQ(block.clobber_list[1].reg, R0);
EXPECT_EQ(block.clobber_list[2].reg, R1);
EXPECT_EQ(block.input_list[0].reg, R0);
EXPECT_EQ(block.input_list[1].reg, R1);
}
}