mirror of
https://github.com/RPCS3/rsx_program_decompiler.git
synced 2026-01-31 01:25:19 +01:00
Fixed dot*, divsq, pow instructions
Fixed argument mask
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerCommandArguments>-elf_extract_fp_cgbin rsx_fp_static_test2.ppu.elf cg.bin</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>-fp_glsl fp_cg.ucode out.glsl</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)bin\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommandArguments>-elf_extract_fp_cgbin rsx_fp_static_test2.ppu.elf cg.bin</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>-fp_glsl fp_cg.ucode out.glsl</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)bin\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LocalDebuggerCommandArguments>-elf_extract_fp_cgbin rsx_fp_static_test2.ppu.elf cg.bin</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>-fp_glsl fp_cg.ucode out.glsl</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)bin\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerCommandArguments>-elf_extract_fp_cgbin rsx_fp_static_test2.ppu.elf cg.bin</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>-fp_glsl fp_cg.ucode out.glsl</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)bin\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace rsx
|
||||
};
|
||||
|
||||
template<int size> struct dest {};
|
||||
template<int index, int size> struct src {};
|
||||
template<int index, int size, bool apply_dst_mask = true> struct src {};
|
||||
struct texture {};
|
||||
struct addr {};
|
||||
struct cond {};
|
||||
@@ -71,8 +71,8 @@ namespace rsx
|
||||
using MUL = instruction < opcode::MUL, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using ADD = instruction < opcode::ADD, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using MAD = instruction < opcode::MAD, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>>, arg<src<2, 4>> >;
|
||||
using DP3 = instruction < opcode::DP3, H | C, dest<3>, arg<src<0, 3>>, arg<src<1, 3>> >;
|
||||
using DP4 = instruction < opcode::DP4, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using DP3 = instruction < opcode::DP3, H | C, dest<3>, arg<src<0, 3, false>>, arg<src<1, 3, false>> >;
|
||||
using DP4 = instruction < opcode::DP4, H | C, dest<4>, arg<src<0, 4, false>>, arg<src<1, 4, false>> >;
|
||||
using DST = instruction < opcode::DST, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using MIN = instruction < opcode::MIN, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using MAX = instruction < opcode::MAX, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
@@ -104,7 +104,7 @@ namespace rsx
|
||||
using SIN = instruction < opcode::SIN, H | C, dest<4>, arg<src<0, 1> > >;
|
||||
using PK2 = instruction < opcode::PK2, H | C, dest<4>, arg<src<0, 4> > >;
|
||||
using UP2 = instruction < opcode::UP2, H | C, dest<4>, arg<src<0, 4> > >;
|
||||
using POW = instruction < opcode::POW, H | C, dest<4>, arg<src<0, 4> > >;
|
||||
using POW = instruction < opcode::POW, H | C, dest<4>, arg<src<0, 4> >, arg<src<1, 4> > >;
|
||||
using PKB = instruction < opcode::PKB, H | C, dest<4>, arg<src<0, 4> > >;
|
||||
using UPB = instruction < opcode::UPB, H | C, dest<4>, arg<src<0, 4> > >;
|
||||
using PK16 = instruction < opcode::PK16, H | C, dest<4>, arg<src<0, 4> > >;
|
||||
@@ -120,10 +120,10 @@ namespace rsx
|
||||
using BEMLUM = instruction < opcode::BEMLUM, H | C, dest<4>, arg<src<0, 4>> >;
|
||||
using REFL = instruction < opcode::REFL, H | C, dest<4>, arg<src<0, 4>> >;
|
||||
using TIMESWTEX = instruction < opcode::TIMESWTEX, H | C, dest<4>, arg<src<0, 4>> >;
|
||||
using DP2 = instruction < opcode::DP2, H | C, dest<2>, arg<src<0, 2>>, arg<src<1, 2>> >;
|
||||
using DP2 = instruction < opcode::DP2, H | C, dest<2>, arg<src<0, 2, false>>, arg<src<1, 2, false>> >;
|
||||
using NRM = instruction < opcode::NRM, H | C, dest<4>, arg<src<0, 4>> >;
|
||||
using DIV = instruction < opcode::DIV, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using DIVSQ = instruction < opcode::LOOP, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using DIVSQ = instruction < opcode::DIVSQ, H | C, dest<4>, arg<src<0, 4>>, arg<src<1, 4>> >;
|
||||
using LIF = instruction < opcode::LIF, H >;
|
||||
using FENCT = instruction < opcode::FENCT, suffix_none >;
|
||||
using FENCB = instruction < opcode::FENCB, suffix_none >;
|
||||
@@ -148,6 +148,8 @@ namespace rsx
|
||||
template<typename decompiler_impl>
|
||||
__forceinline static void function(decompiler<decompiler_impl>& decompiler)
|
||||
{
|
||||
if (id != opcode::FENCT && id != opcode::FENCT)
|
||||
throw std::runtime_error("unimplemented instruction: " + instructions_names[(std::size_t)id]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -188,8 +190,8 @@ namespace rsx
|
||||
{
|
||||
};
|
||||
|
||||
template<int index, int count>
|
||||
struct expand_arg_t<src<index, count>>
|
||||
template<int index, int count, bool apply_dst_mask>
|
||||
struct expand_arg_t<src<index, count, apply_dst_mask>>
|
||||
{
|
||||
template<typename decompiler_impl>
|
||||
__forceinline static program_variable impl(decompiler<decompiler_impl>& decompiler)
|
||||
@@ -288,6 +290,20 @@ namespace rsx
|
||||
|
||||
variable.mask.add(swizzle);
|
||||
|
||||
if (apply_dst_mask)
|
||||
{
|
||||
variable.mask.add(decompiler.dst_mask<count>().to_string()).symplify();
|
||||
}
|
||||
|
||||
if (count != 4)
|
||||
{
|
||||
std::string mask = variable.mask.to_string();
|
||||
if (mask.empty())
|
||||
mask = "xyzw";
|
||||
|
||||
variable.mask = mask_t{}.add(mask.substr(0, count));
|
||||
}
|
||||
|
||||
if (need_declare)
|
||||
variable = decompiler.info.vars.add(variable);
|
||||
|
||||
@@ -315,6 +331,7 @@ namespace rsx
|
||||
result.name = "texture";
|
||||
result.index = decompiler.ucode.dst.tex_num;
|
||||
result.size = 1;
|
||||
result.type = program_variable_type::texture;
|
||||
return decompiler.info.vars.add(decompiler_impl::texture_variable(result));
|
||||
}
|
||||
};
|
||||
@@ -332,6 +349,20 @@ namespace rsx
|
||||
public:
|
||||
std::unordered_set<std::string> functions_set;
|
||||
|
||||
template<int count>
|
||||
mask_t dst_mask()
|
||||
{
|
||||
static const std::string mask = "xyzw";
|
||||
|
||||
std::string swizzle;
|
||||
if (ucode.dst.mask_x) swizzle += mask[0];
|
||||
if (ucode.dst.mask_y) swizzle += mask[1];
|
||||
if (ucode.dst.mask_z) swizzle += mask[2];
|
||||
if (ucode.dst.mask_w) swizzle += mask[3];
|
||||
|
||||
return mask_t{}.add(swizzle.substr(0, count));
|
||||
}
|
||||
|
||||
template<u32 flags, int count>
|
||||
program_variable dst()
|
||||
{
|
||||
@@ -342,16 +373,7 @@ namespace rsx
|
||||
result.index = ucode.dst.dest_reg;
|
||||
result.name = ucode.dst.fp16 ? "H" : "R";
|
||||
result.size = count;
|
||||
|
||||
static const std::string mask = "xyzw";
|
||||
|
||||
std::string swizzle;
|
||||
if (ucode.dst.mask_x) swizzle += mask[0];
|
||||
if (ucode.dst.mask_y) swizzle += mask[1];
|
||||
if (ucode.dst.mask_z) swizzle += mask[2];
|
||||
if (ucode.dst.mask_w) swizzle += mask[3];
|
||||
|
||||
result.mask.add(swizzle);
|
||||
result.mask = dst_mask<count>();
|
||||
|
||||
return info.vars.add(result);
|
||||
}
|
||||
@@ -369,6 +391,7 @@ namespace rsx
|
||||
result.name = "CC";
|
||||
result.index = ucode.src0.cond_mod_reg_index;
|
||||
result.size = 4;
|
||||
result.mask = dst_mask<4>();
|
||||
|
||||
return info.vars.add(result);
|
||||
}
|
||||
@@ -405,9 +428,9 @@ namespace rsx
|
||||
set_code_line(decompiler_impl::set_dst<id, flags, count>(this, arg0, arg1, arg2));
|
||||
}
|
||||
|
||||
void unknown_instruction(u32 opcode)
|
||||
void unknown_instruction(opcode op)
|
||||
{
|
||||
throw std::runtime_error("unimplemented instruction '" + instructions_names[opcode] + "' (" + std::to_string(opcode) + ") #"
|
||||
throw std::runtime_error("unimplemented instruction '" + instructions_names[(std::size_t)op] + "' (" + std::to_string((std::size_t)op) + ") #"
|
||||
+ std::to_string(ucode_index));
|
||||
}
|
||||
|
||||
@@ -449,38 +472,19 @@ namespace rsx
|
||||
|
||||
ucode = ucode_ptr[ucode_index].unpack();
|
||||
|
||||
const u32 opcode = ucode.dst.opcode | (ucode.src1.opcode_is_branch << 6);
|
||||
const fragment_program::opcode opcode = fragment_program::opcode(ucode.dst.opcode | (ucode.src1.opcode_is_branch << 6));
|
||||
|
||||
//if (ucode_index == 20)
|
||||
// break;
|
||||
|
||||
if (opcode != 0)
|
||||
if (opcode != fragment_program::opcode::NOP)
|
||||
{
|
||||
auto function = instructions[opcode];
|
||||
auto function = instructions[(std::size_t)opcode];
|
||||
|
||||
try
|
||||
if (function)
|
||||
{
|
||||
if (function)
|
||||
{
|
||||
function(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
unknown_instruction(opcode);
|
||||
}
|
||||
function(*this);
|
||||
}
|
||||
catch (...)
|
||||
else
|
||||
{
|
||||
std::exception_ptr ex_p = std::current_exception();
|
||||
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(ex_p);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
throw std::out_of_range(ex.what());
|
||||
}
|
||||
unknown_instruction(opcode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace rsx
|
||||
case program_variable_type::input: result += "in "; break;
|
||||
case program_variable_type::output: result += "layout(location = " + std::to_string(var.second.index) + ") out "; break;
|
||||
case program_variable_type::constant: result += "uniform "; break;
|
||||
case program_variable_type::texture: result += "layout(binding = " + std::to_string(var.second.index) + ") uniform "; break;
|
||||
}
|
||||
|
||||
if (var.second.storage_type.empty())
|
||||
@@ -51,8 +52,6 @@ namespace rsx
|
||||
__forceinline static program_variable texture_variable(program_variable arg)
|
||||
{
|
||||
arg.storage_type = "sampler2D";
|
||||
arg.type = program_variable_type::constant;
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
@@ -67,11 +66,41 @@ namespace rsx
|
||||
else
|
||||
{
|
||||
assert(arg.constant.type == program_constant_type::f32);
|
||||
result = fmt::format("vec4(%g, %g, %g, %g)",
|
||||
arg.constant.x.f32_value,
|
||||
arg.constant.y.f32_value,
|
||||
arg.constant.z.f32_value,
|
||||
arg.constant.w.f32_value);
|
||||
|
||||
std::string mask = arg.mask.to_string();
|
||||
std::unordered_map<char, float> constant_map =
|
||||
{
|
||||
{ 'x', arg.constant.x.f32_value },
|
||||
{ 'y', arg.constant.y.f32_value },
|
||||
{ 'z', arg.constant.z.f32_value },
|
||||
{ 'w', arg.constant.w.f32_value },
|
||||
};
|
||||
|
||||
if (mask.empty())
|
||||
{
|
||||
result = fmt::format("vec4(%g, %g, %g, %g)",
|
||||
arg.constant.x.f32_value,
|
||||
arg.constant.y.f32_value,
|
||||
arg.constant.z.f32_value,
|
||||
arg.constant.w.f32_value);
|
||||
}
|
||||
else if (mask.size() == 1)
|
||||
{
|
||||
result = fmt::format("%g", constant_map[mask[0]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = fmt::format("vec%d(", mask.size());
|
||||
|
||||
for (size_t i = 0; i < mask.size(); ++i)
|
||||
{
|
||||
if (i)
|
||||
result += ", ";
|
||||
result += fmt::format("%g", constant_map[mask[i]]);
|
||||
}
|
||||
|
||||
result += ")";
|
||||
}
|
||||
}
|
||||
|
||||
if (arg.is_abs)
|
||||
@@ -120,7 +149,7 @@ namespace rsx
|
||||
"ddx", "ddy", "texture", "txp", "txd", "rcp", "rsq",
|
||||
"exp2", "log2", "lit", "lrp", "str", "sfl", "cos",
|
||||
"sin", "pk2", "up2", "pow", "pkb", "upb", "pk16",
|
||||
"up16", "bem" "pkg", "upg", "dpa2", "txl", "?",
|
||||
"up16", "bem", "pkg", "upg", "dpa2", "txl", "?",
|
||||
"txb", "?", "texbem", "txpbem", "bemlum", "refl", "timeswtex",
|
||||
"dot", "normalize", "?", "divsq", "lif", "fenct", "fencb",
|
||||
"?", "break", "cal", "ife", "loop", "rep", "return"
|
||||
@@ -138,17 +167,17 @@ namespace rsx
|
||||
|
||||
if (!arg0.is_null())
|
||||
{
|
||||
value += variable_to_string(arg0);
|
||||
value = variable_to_string(arg0);
|
||||
|
||||
if (!arg1.is_null())
|
||||
{
|
||||
value += " " + std::string(1, operators[(std::size_t)id]) + " " + variable_to_string(arg1);
|
||||
value = "(" + value + " " + std::string(1, operators[(std::size_t)id]) + " " + variable_to_string(arg1) + ")";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case opcode::DIVSQ:
|
||||
value += variable_to_string(arg0) + " / sqrt(" + variable_to_string(arg1) + ")";
|
||||
value = "(" + variable_to_string(arg0) + " / sqrt(" + variable_to_string(arg1) + "))";
|
||||
break;
|
||||
|
||||
case opcode::LIF:
|
||||
@@ -255,12 +284,13 @@ namespace rsx
|
||||
{
|
||||
program_variable execution_condition = dec->execution_condition();
|
||||
mask_t update_mask;
|
||||
update_mask.add(dst.mask.to_string());
|
||||
update_mask.add(execution_condition.mask.to_string());
|
||||
update_mask.add(fmt::string("xyzw").substr(0, count));
|
||||
update_mask
|
||||
.add(execution_condition.mask.to_string())
|
||||
.add(dst.mask.to_string());
|
||||
|
||||
update_mask = mask_t{}.add(update_mask.to_string().substr(0, count));
|
||||
|
||||
fmt::string execution_condition_string = execution_condition;
|
||||
|
||||
std::string execution_condition_operation;
|
||||
|
||||
if (dec->ucode.src0.exec_if_gr && dec->ucode.src0.exec_if_eq)
|
||||
|
||||
@@ -75,6 +75,16 @@ namespace rsx
|
||||
return symplify().to_string_impl();
|
||||
}
|
||||
|
||||
std::string mask_t::apply_to(const std::string& expr) const
|
||||
{
|
||||
std::string mask = to_string();
|
||||
|
||||
if (mask.empty())
|
||||
return expr;
|
||||
|
||||
return expr + "." + mask;
|
||||
}
|
||||
|
||||
std::string program_variable::to_string_impl() const
|
||||
{
|
||||
if (array_size)
|
||||
@@ -83,11 +93,6 @@ namespace rsx
|
||||
return index != ~0 ? name + std::to_string(index) : name;
|
||||
}
|
||||
|
||||
std::string program_variable::append_dot_if_not_empty(const std::string& string) const
|
||||
{
|
||||
return string.empty() ? std::string{} : "." + string;
|
||||
};
|
||||
|
||||
std::string program_variable::storage_name() const
|
||||
{
|
||||
return name + (array_size ? "[" + std::to_string(array_size + 1) + "]" : (index != ~0 ? std::to_string(index) : std::string{}));
|
||||
@@ -95,12 +100,12 @@ namespace rsx
|
||||
|
||||
std::string program_variable::to_string() const
|
||||
{
|
||||
return to_string_impl() + append_dot_if_not_empty(mask.to_string());
|
||||
return mask.apply_to(to_string_impl());
|
||||
}
|
||||
|
||||
std::string program_variable::to_string()
|
||||
{
|
||||
return to_string_impl() + append_dot_if_not_empty(mask.to_string());
|
||||
return mask.symplify().apply_to(to_string_impl());
|
||||
}
|
||||
|
||||
bool program_variable::is_null() const
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace rsx
|
||||
none,
|
||||
input,
|
||||
output,
|
||||
constant
|
||||
constant,
|
||||
texture
|
||||
};
|
||||
|
||||
struct mask_t
|
||||
@@ -27,6 +28,8 @@ namespace rsx
|
||||
public:
|
||||
std::string to_string() const;
|
||||
std::string to_string();
|
||||
|
||||
std::string apply_to(const std::string& std) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -70,7 +73,6 @@ namespace rsx
|
||||
|
||||
private:
|
||||
std::string to_string_impl() const;
|
||||
std::string append_dot_if_not_empty(const std::string& string) const;
|
||||
|
||||
public:
|
||||
std::string storage_name() const;
|
||||
|
||||
Reference in New Issue
Block a user