rsx/asm: Add support for more opcodes and add tests for mixed block IO
This commit is contained in:
@@ -8,6 +8,32 @@
|
|||||||
|
|
||||||
namespace rsx::assembler
|
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* FPIR::load(const RegisterRef& ref, int operand, Instruction* prev)
|
||||||
{
|
{
|
||||||
Instruction* target = prev;
|
Instruction* target = prev;
|
||||||
@@ -233,39 +259,15 @@ namespace rsx::assembler
|
|||||||
inst->bytecode[1] = s0.HEX; \
|
inst->bytecode[1] = s0.HEX; \
|
||||||
} while (0)
|
} 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);
|
fmt::throw_exception("Unhandled instruction '%s'", op);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == "ADD")
|
SET_OPCODE(found->second);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef SET_OPCODE
|
#undef SET_OPCODE
|
||||||
|
|
||||||
fmt::throw_exception("Unhandled instruction '%s'", op);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string op, dst;
|
std::string op, dst;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace rsx::assembler
|
|||||||
|
|
||||||
TEST(TestFPIR, RegisterAnnotationPass)
|
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"(
|
auto graph = CFG_from_source(R"(
|
||||||
ADD R1, R0, R1;
|
ADD R1, R0, R1;
|
||||||
MOV H0, H4;
|
MOV H0, H4;
|
||||||
@@ -99,4 +99,34 @@ namespace rsx::assembler
|
|||||||
EXPECT_EQ(block.input_list[1].reg, R0);
|
EXPECT_EQ(block.input_list[1].reg, R0);
|
||||||
EXPECT_EQ(block.input_list[2].reg, R1);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user