- Different from C++ amateur.
- Addresses code review suggestions to step up the C++
This commit is contained in:
kd-11 2025-12-09 03:04:03 +03:00 committed by kd-11
parent a412e34fa6
commit 2c6d3dde67
4 changed files with 43 additions and 57 deletions

View File

@ -19,7 +19,7 @@ namespace rsx::assembler
bool set_cond; bool set_cond;
}; };
static std::unordered_map<std::string, FP_opcode_encoding_t> s_opcode_lookup static std::unordered_map<std::string_view, FP_opcode_encoding_t> s_opcode_lookup
{ {
// Arithmetic // Arithmetic
{ "NOP", { .op = RSX_FP_OPCODE_NOP, .exec_if_lt = true, .exec_if_eq = true, .exec_if_gt = true, .set_cond = false } }, { "NOP", { .op = RSX_FP_OPCODE_NOP, .exec_if_lt = true, .exec_if_eq = true, .exec_if_gt = true, .set_cond = false } },
@ -168,10 +168,9 @@ namespace rsx::assembler
std::vector<u32> result; std::vector<u32> result;
result.reserve(m_instructions.size() * 4); result.reserve(m_instructions.size() * 4);
for (u32 i = 0; i < m_instructions.size(); ++i) for (const auto& inst : m_instructions)
{ {
const auto& inst = m_instructions[i]; const auto src = reinterpret_cast<const be_t<u16>*>(inst.bytecode);
auto src = reinterpret_cast<const be_t<u16>*>(inst.bytecode);
for (u32 j = 0; j < inst.length; ++j) for (u32 j = 0; j < inst.length; ++j)
{ {
const u16 low = src[j * 2]; const u16 low = src[j * 2];
@ -184,7 +183,7 @@ namespace rsx::assembler
return result; return result;
} }
FPIR FPIR::from_source(const std::string& asm_) FPIR FPIR::from_source(std::string_view asm_)
{ {
std::vector<std::string> instructions = fmt::split(asm_, { "\n", ";" }); std::vector<std::string> instructions = fmt::split(asm_, { "\n", ";" });
if (instructions.empty()) if (instructions.empty())
@ -192,13 +191,13 @@ namespace rsx::assembler
return {}; return {};
} }
auto transform_inst = [](const std::string& s) auto transform_inst = [](std::string_view s)
{ {
std::string result; std::string result;
result.reserve(s.size()); result.reserve(s.size());
bool literal = false; bool literal = false;
for (auto& c : s) for (const auto& c : s)
{ {
if (c == ' ') if (c == ' ')
{ {
@ -235,7 +234,7 @@ namespace rsx::assembler
return result; return result;
}; };
auto decode_instruction = [&](const std::string& inst, std::string& op, std::string& dst, std::vector<std::string>& sources) auto decode_instruction = [&](std::string_view inst, std::string& op, std::string& dst, std::vector<std::string>& sources)
{ {
const auto i = transform_inst(inst); const auto i = transform_inst(inst);
if (i.empty()) if (i.empty())
@ -259,7 +258,7 @@ namespace rsx::assembler
} }
}; };
auto get_ref = [](const std::string& reg) auto get_ref = [](std::string_view reg)
{ {
ensure(reg.length() > 1, "Invalid register specifier"); ensure(reg.length() > 1, "Invalid register specifier");
@ -291,15 +290,15 @@ namespace rsx::assembler
return ref; return ref;
}; };
auto get_constants = [](const std::string& reg) -> std::array<f32, 4> auto get_constants = [](std::string_view reg) -> std::array<f32, 4>
{ {
float x, y, z, w; float x, y, z, w;
if (sscanf_s(reg.c_str(), "#{%f|%f|%f|%f}", &x, &y, &z, &w) == 4) if (sscanf_s(reg.data(), "#{%f|%f|%f|%f}", &x, &y, &z, &w) == 4)
{ {
return { x, y, z, w }; return { x, y, z, w };
} }
if (sscanf_s(reg.c_str(), "#{%f}", &x) == 1) if (sscanf_s(reg.data(), "#{%f}", &x) == 1)
{ {
return { x, x, x, x }; return { x, x, x, x };
} }
@ -328,35 +327,29 @@ namespace rsx::assembler
} }
}; };
auto encode_opcode = [](const std::string& op, Instruction* inst) auto encode_opcode = [](std::string_view op, Instruction* inst)
{ {
OPDEST d0 { .HEX = inst->bytecode[0] }; OPDEST d0 { .HEX = inst->bytecode[0] };
SRC0 s0 { .HEX = inst->bytecode[1] }; SRC0 s0 { .HEX = inst->bytecode[1] };
SRC1 s1 { .HEX = inst->bytecode[2] }; SRC1 s1 { .HEX = inst->bytecode[2] };
#define SET_OPCODE(encoding) \
do { \
inst->opcode = encoding.op; \
d0.opcode = encoding.op & 0x3F; \
s1.opcode_hi = (encoding.op > 0x3F)? 1 : 0; \
s0.exec_if_eq = encoding.exec_if_eq ? 1 : 0; \
s0.exec_if_gr = encoding.exec_if_gt ? 1 : 0; \
s0.exec_if_lt = encoding.exec_if_lt ? 1 : 0; \
d0.set_cond = encoding.set_cond ? 1 : 0; \
inst->bytecode[0] = d0.HEX; \
inst->bytecode[1] = s0.HEX; \
inst->bytecode[2] = s1.HEX; \
} while (0)
const auto found = s_opcode_lookup.find(op); const auto found = s_opcode_lookup.find(op);
if (found == s_opcode_lookup.end()) if (found == s_opcode_lookup.end())
{ {
fmt::throw_exception("Unhandled instruction '%s'", op); fmt::throw_exception("Unhandled instruction '%s'", op);
} }
const auto& encoding = found->second;
SET_OPCODE(found->second); inst->opcode = encoding.op;
d0.opcode = encoding.op & 0x3F;
#undef SET_OPCODE s1.opcode_hi = (encoding.op > 0x3F)? 1 : 0;
s0.exec_if_eq = encoding.exec_if_eq ? 1 : 0;
s0.exec_if_gr = encoding.exec_if_gt ? 1 : 0;
s0.exec_if_lt = encoding.exec_if_lt ? 1 : 0;
d0.set_cond = encoding.set_cond ? 1 : 0;
inst->bytecode[0] = d0.HEX;
inst->bytecode[1] = s0.HEX;
inst->bytecode[2] = s1.HEX;
}; };
std::string op, dst; std::string op, dst;

View File

@ -16,7 +16,7 @@ namespace rsx::assembler
const std::vector<Instruction>& instructions() const; const std::vector<Instruction>& instructions() const;
std::vector<u32> compile() const; std::vector<u32> compile() const;
static FPIR from_source(const std::string& asm_); static FPIR from_source(std::string_view asm_);
private: private:
Instruction* load(const RegisterRef& reg, int operand, Instruction* target = nullptr); Instruction* load(const RegisterRef& reg, int operand, Instruction* target = nullptr);

View File

@ -16,9 +16,9 @@ namespace rsx::assembler::FP
bool is_delay_slot(const Instruction& instruction) bool is_delay_slot(const Instruction& instruction)
{ {
OPDEST dst{ .HEX = instruction.bytecode[0] }; const OPDEST dst{ .HEX = instruction.bytecode[0] };
SRC0 src0{ .HEX = instruction.bytecode[1] }; const SRC0 src0{ .HEX = instruction.bytecode[1] };
SRC1 src1{ .HEX = instruction.bytecode[2] }; const SRC1 src1{ .HEX = instruction.bytecode[2] };
if (dst.opcode != RSX_FP_OPCODE_MOV || // These slots are always populated with MOV if (dst.opcode != RSX_FP_OPCODE_MOV || // These slots are always populated with MOV
dst.no_dest || // Must have a sink dst.no_dest || // Must have a sink
@ -70,21 +70,14 @@ namespace rsx::assembler::FP
if (ref) if (ref)
{ {
results.push_back(ref); results.push_back(std::move(ref));
} }
} }
// Helper to check a span for 32-bit access // Helper to check a span for 32-bit access
auto match_any_32 = [](const std::span<const char> lanes) auto match_any_32 = [](const std::span<const char> lanes)
{ {
for (const auto& c : lanes) return std::any_of(lanes.begin(), lanes.end(), FN(x == content_dual || x == content_float32));
{
if (c == content_dual || c == content_float32)
{
return true;
}
}
return false;
}; };
// F32 register processing // F32 register processing
@ -115,7 +108,7 @@ namespace rsx::assembler::FP
if (ref) if (ref)
{ {
results.push_back(ref); results.push_back(std::move(ref));
} }
} }
@ -142,13 +135,13 @@ namespace rsx::assembler::FP
continue; continue;
} }
instruction.srcs.push_back(reg); instruction.srcs.push_back(std::move(reg));
} }
RegisterRef dst = get_dst_register(&instruction); RegisterRef dst = get_dst_register(&instruction);
if (dst) if (dst)
{ {
instruction.dsts.push_back(dst); instruction.dsts.push_back(std::move(dst));
} }
} }
} }

View File

@ -57,7 +57,7 @@ namespace rsx::assembler::FP
RegisterRef ref{ .reg{.id = static_cast<int>(index), .f16 = true } }; RegisterRef ref{ .reg{.id = static_cast<int>(index), .f16 = true } };
ref.mask = mask; ref.mask = mask;
result.push_back(ref); result.push_back(std::move(ref));
} }
return result; return result;
} }
@ -94,7 +94,7 @@ namespace rsx::assembler::FP
} }
ref.reg = {.id = static_cast<int>(index), .f16 = false }; ref.reg = {.id = static_cast<int>(index), .f16 = false };
result.push_back(barrier); result.push_back(std::move(barrier));
} }
return result; return result;
@ -190,7 +190,7 @@ namespace rsx::assembler::FP
Register src_reg{ .id = static_cast<int>(src_reg_id), .f16 = true }; Register src_reg{ .id = static_cast<int>(src_reg_id), .f16 = true };
instruction.srcs.push_back({ .reg = src_reg, .mask = 0xF }); instruction.srcs.push_back({ .reg = src_reg, .mask = 0xF });
instruction.dsts.push_back({ .reg{ .id = reg_id, .f16 = false }, .mask = (1u << ch) }); instruction.dsts.push_back({ .reg{ .id = reg_id, .f16 = false }, .mask = (1u << ch) });
result.push_back(instruction); result.push_back(std::move(instruction));
} }
return result; return result;
@ -258,7 +258,7 @@ namespace rsx::assembler::FP
Register src_reg{ .id = static_cast<int>(src_reg_id), .f16 = true }; Register src_reg{ .id = static_cast<int>(src_reg_id), .f16 = true };
instruction.srcs.push_back({ .reg = src_reg, .mask = 0xF }); instruction.srcs.push_back({ .reg = src_reg, .mask = 0xF });
instruction.dsts.push_back({ .reg{.id = reg.reg.id, .f16 = false }, .mask = dst.write_mask }); instruction.dsts.push_back({ .reg{.id = reg.reg.id, .f16 = false }, .mask = dst.write_mask });
result.push_back(instruction); result.push_back(std::move(instruction));
} }
return result; return result;
@ -284,7 +284,7 @@ namespace rsx::assembler::FP
for (const auto& barrier : barriers) for (const auto& barrier : barriers)
{ {
auto instructions = build_barrier32(barrier); auto instructions = build_barrier32(barrier);
result.insert(result.end(), instructions.begin(), instructions.end()); result.insert(result.end(), std::make_move_iterator(instructions.begin()), std::make_move_iterator(instructions.end()));
} }
return result; return result;
@ -351,10 +351,10 @@ namespace rsx::assembler::FP
for (const auto& reg : barrier16_in) for (const auto& reg : barrier16_in)
{ {
auto barrier = build_barrier16(reg); auto barrier = build_barrier16(reg);
instructions.insert(instructions.end(), barrier.begin(), barrier.end()); instructions.insert(instructions.end(), std::make_move_iterator(barrier.begin()), std::make_move_iterator(barrier.end()));
} }
it = block->instructions.insert(it, instructions.begin(), instructions.end()); it = block->instructions.insert(it, std::make_move_iterator(instructions.begin()), std::make_move_iterator(instructions.end()));
std::advance(it, instructions.size()); std::advance(it, instructions.size());
} }
@ -367,10 +367,10 @@ namespace rsx::assembler::FP
for (const auto& reg : barrier32_in) for (const auto& reg : barrier32_in)
{ {
auto barrier = build_barrier32(reg); auto barrier = build_barrier32(reg);
instructions.insert(instructions.end(), barrier.begin(), barrier.end()); instructions.insert(instructions.end(), std::make_move_iterator(barrier.begin()), std::make_move_iterator(barrier.end()));
} }
it = block->instructions.insert(it, instructions.begin(), instructions.end()); it = block->instructions.insert(it, std::make_move_iterator(instructions.begin()), std::make_move_iterator(instructions.end()));
std::advance(it, instructions.size()); std::advance(it, instructions.size());
} }
} }
@ -431,8 +431,8 @@ namespace rsx::assembler::FP
if (!clobbered_lanes.empty()) if (!clobbered_lanes.empty())
{ {
const auto instructions = resolve_dependencies(clobbered_lanes, f16); auto instructions = resolve_dependencies(clobbered_lanes, f16);
target->epilogue.insert(target->epilogue.end(), instructions.begin(), instructions.end()); target->epilogue.insert(target->epilogue.end(), std::make_move_iterator(instructions.begin()), std::make_move_iterator(instructions.end()));
} }
if (lanes_to_search.empty()) if (lanes_to_search.empty())