[shader_recompiler/Maxwell] Rewrite ISBERD and fix potential downsides #192
1 changed files with 54 additions and 37 deletions
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
namespace Shader::Maxwell {
|
namespace Shader::Maxwell {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum class Mode : u64 {
|
enum class Mode : u64 {
|
||||||
Default,
|
Default,
|
||||||
Patch,
|
Patch,
|
||||||
|
@ -39,66 +40,82 @@ void TranslatorVisitor::ISBERD(u64 insn) {
|
||||||
BitField<47, 2, Shift> shift;
|
BitField<47, 2, Shift> shift;
|
||||||
} const isberd{insn};
|
} const isberd{insn};
|
||||||
|
|
||||||
if (isberd.skew != 0) {
|
bool is_only_skew_op = true;
|
||||||
IR::U32 current_lane_id{ir.LaneId()};
|
bool no_other_op = true;
|
||||||
IR::U32 result{ir.IAdd(X(isberd.src_reg), current_lane_id)};
|
auto apply_shift = [&](IR::U32 result) -> IR::U32 {
|
||||||
X(isberd.dest_reg, result);
|
switch (isberd.shift.Value()) {
|
||||||
}
|
case Shift::U16:
|
||||||
|
case Shift::B32:
|
||||||
|
return ir.ShiftLeftLogical(result, ir.Imm32(1));
|
||||||
|
default:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (isberd.o != 0) {
|
if (isberd.o != 0) {
|
||||||
IR::U32 address{};
|
IR::U32 address{};
|
||||||
IR::F32 result{};
|
|
||||||
if (isberd.src_reg_num == 0xFF) {
|
if (isberd.src_reg_num == 0xFF) {
|
||||||
address = ir.Imm32(isberd.imm);
|
address = ir.Imm32(isberd.imm);
|
||||||
result = ir.GetAttributeIndexed(address);
|
|
||||||
} else {
|
} else {
|
||||||
IR::U32 offset = ir.Imm32(isberd.imm);
|
IR::U32 offset = ir.Imm32(isberd.imm);
|
||||||
address = ir.IAdd(X(isberd.src_reg), offset);
|
address = ir.IAdd(X(isberd.src_reg), offset);
|
||||||
result = ir.GetAttributeIndexed(address);
|
if (isberd.skew != 0) {
|
||||||
|
address = ir.IAdd(address, ir.LaneId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
X(isberd.dest_reg, ir.BitCast<IR::U32>(result));
|
|
||||||
|
IR::U32 result = ir.BitCast<IR::U32>(ir.GetAttributeIndexed(address));
|
||||||
|
if (isberd.shift != Shift::Default) {
|
||||||
|
result = apply_shift(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_only_skew_op = false;
|
||||||
|
no_other_op = false;
|
||||||
|
X(isberd.dest_reg, result);
|
||||||
}
|
}
|
||||||
if (isberd.mode != Mode::Default) {
|
|
||||||
IR::F32 result{};
|
else if (isberd.mode != Mode::Default) {
|
||||||
IR::U32 index{};
|
IR::U32 index{};
|
||||||
if (isberd.src_reg_num == 0xFF) {
|
if (isberd.src_reg_num == 0xFF) {
|
||||||
index = ir.Imm32(isberd.imm);
|
index = ir.Imm32(isberd.imm);
|
||||||
} else {
|
} else {
|
||||||
index = ir.IAdd(X(isberd.src_reg), ir.Imm32(isberd.imm));
|
index = ir.IAdd(X(isberd.src_reg), ir.Imm32(isberd.imm));
|
||||||
|
if (isberd.skew != 0) {
|
||||||
|
index = ir.IAdd(index, ir.LaneId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (static_cast<u64>(isberd.mode.Value())) {
|
IR::F32 result_f32{};
|
||||||
case static_cast<u64>(Mode::Patch):
|
switch (isberd.mode.Value()) {
|
||||||
result = ir.GetPatch(index.Patch());
|
case Mode::Patch:
|
||||||
|
result_f32 = ir.GetPatch(index.Patch());
|
||||||
break;
|
break;
|
||||||
case static_cast<u64>(Mode::Prim):
|
case Mode::Prim:
|
||||||
result = ir.GetAttribute(index.Attribute());
|
result_f32 = ir.GetAttribute(index.Attribute());
|
||||||
break;
|
break;
|
||||||
case static_cast<u64>(Mode::Attr):
|
case Mode::Attr:
|
||||||
result = ir.GetAttributeIndexed(index);
|
result_f32 = ir.GetAttributeIndexed(index);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
X(isberd.dest_reg, ir.BitCast<IR::U32>(result));
|
|
||||||
}
|
IR::U32 result_u32 = ir.BitCast<IR::U32>(result_f32);
|
||||||
if (isberd.shift != Shift::Default) {
|
if (isberd.shift != Shift::Default) {
|
||||||
IR::U32 result{};
|
result_u32 = apply_shift(result_u32);
|
||||||
switch (static_cast<u64>(isberd.shift.Value())) {
|
|
||||||
case static_cast<u64>(Shift::U16):
|
|
||||||
result = ir.ShiftLeftLogical(result, static_cast<IR::U32>(ir.Imm16(1)));
|
|
||||||
break;
|
|
||||||
case static_cast<u64>(Shift::B32):
|
|
||||||
result = ir.ShiftLeftLogical(result, ir.Imm32(1));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
X(isberd.dest_reg, result);
|
|
||||||
|
is_only_skew_op = false;
|
||||||
|
no_other_op = false;
|
||||||
|
X(isberd.dest_reg, result_u32);
|
||||||
}
|
}
|
||||||
//LOG_DEBUG(Shader, "(STUBBED) called {}", insn);
|
|
||||||
if (isberd.src_reg_num == 0xFF) {
|
if (isberd.skew != 0 && is_only_skew_op) {
|
||||||
IR::U32 src_imm{ir.Imm32(static_cast<u32>(isberd.imm))};
|
IR::U32 result = ir.IAdd(X(isberd.src_reg), ir.LaneId());
|
||||||
IR::U32 result{ir.IAdd(X(isberd.src_reg), src_imm)};
|
|
||||||
X(isberd.dest_reg, result);
|
X(isberd.dest_reg, result);
|
||||||
} else {
|
} else if (no_other_op) {
|
||||||
X(isberd.dest_reg, X(isberd.src_reg));
|
X(isberd.dest_reg, X(isberd.src_reg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::Maxwell
|
} // namespace Shader::Maxwell
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue