|
|
|
@ -10,6 +10,7 @@ |
|
|
|
|
|
|
|
namespace Shader::Maxwell { |
|
|
|
namespace { |
|
|
|
|
|
|
|
enum class Mode : u64 { |
|
|
|
Default, |
|
|
|
Patch, |
|
|
|
@ -39,65 +40,76 @@ void TranslatorVisitor::ISBERD(u64 insn) { |
|
|
|
BitField<47, 2, Shift> shift; |
|
|
|
} const isberd{insn}; |
|
|
|
|
|
|
|
if (isberd.skew != 0) { |
|
|
|
IR::U32 current_lane_id{ir.LaneId()}; |
|
|
|
IR::U32 result{ir.IAdd(X(isberd.src_reg), current_lane_id)}; |
|
|
|
X(isberd.dest_reg, result); |
|
|
|
bool is_only_skew_op = true; |
|
|
|
auto apply_shift = [&](IR::U32 result) -> IR::U32 { |
|
|
|
switch (isberd.shift.Value()) { |
|
|
|
case Shift::U16: |
|
|
|
case Shift::B32: |
|
|
|
return ir.ShiftLeftLogical(result, ir.Imm32(1)); |
|
|
|
default: |
|
|
|
return result; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
if (isberd.o != 0) { |
|
|
|
IR::U32 address{}; |
|
|
|
IR::F32 result{}; |
|
|
|
if (isberd.src_reg_num == 0xFF) { |
|
|
|
address = ir.Imm32(isberd.imm); |
|
|
|
result = ir.GetAttributeIndexed(address); |
|
|
|
} else { |
|
|
|
IR::U32 offset = ir.Imm32(isberd.imm); |
|
|
|
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; |
|
|
|
X(isberd.dest_reg, result); |
|
|
|
} |
|
|
|
if (isberd.mode != Mode::Default) { |
|
|
|
IR::F32 result{}; |
|
|
|
|
|
|
|
else if (isberd.mode != Mode::Default) { |
|
|
|
IR::U32 index{}; |
|
|
|
if (isberd.src_reg_num == 0xFF) { |
|
|
|
index = ir.Imm32(isberd.imm); |
|
|
|
} else { |
|
|
|
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())) { |
|
|
|
case static_cast<u64>(Mode::Patch): |
|
|
|
result = ir.GetPatch(index.Patch()); |
|
|
|
IR::F32 result_f32{}; |
|
|
|
switch (isberd.mode.Value()) { |
|
|
|
case Mode::Patch: |
|
|
|
result_f32 = ir.GetPatch(index.Patch()); |
|
|
|
break; |
|
|
|
case static_cast<u64>(Mode::Prim): |
|
|
|
result = ir.GetAttribute(index.Attribute()); |
|
|
|
case Mode::Prim: |
|
|
|
result_f32 = ir.GetAttribute(index.Attribute()); |
|
|
|
break; |
|
|
|
case static_cast<u64>(Mode::Attr): |
|
|
|
result = ir.GetAttributeIndexed(index); |
|
|
|
case Mode::Attr: |
|
|
|
result_f32 = ir.GetAttributeIndexed(index); |
|
|
|
break; |
|
|
|
default: |
|
|
|
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) { |
|
|
|
IR::U32 result{}; |
|
|
|
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; |
|
|
|
result_u32 = apply_shift(result_u32); |
|
|
|
} |
|
|
|
X(isberd.dest_reg, result); |
|
|
|
|
|
|
|
is_only_skew_op = false; |
|
|
|
X(isberd.dest_reg, result_u32); |
|
|
|
} |
|
|
|
//LOG_DEBUG(Shader, "(STUBBED) called {}", insn);
|
|
|
|
if (isberd.src_reg_num == 0xFF) { |
|
|
|
IR::U32 src_imm{ir.Imm32(static_cast<u32>(isberd.imm))}; |
|
|
|
IR::U32 result{ir.IAdd(X(isberd.src_reg), src_imm)}; |
|
|
|
|
|
|
|
if (isberd.skew != 0 && is_only_skew_op) { |
|
|
|
IR::U32 result = ir.IAdd(X(isberd.src_reg), ir.LaneId()); |
|
|
|
X(isberd.dest_reg, result); |
|
|
|
} else { |
|
|
|
X(isberd.dest_reg, X(isberd.src_reg)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|