Fixed dot*, divsq, pow instructions

Fixed argument mask
This commit is contained in:
DH
2015-08-06 01:21:36 +03:00
parent 50810f548a
commit e1ef4dc7d6
5 changed files with 115 additions and 74 deletions

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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;