shader_decode: Implement IADD3
This commit is contained in:
parent
a40fd07516
commit
4fd06efeb9
@ -9,6 +9,7 @@
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
||||
using Tegra::Shader::IAdd3Height;
|
||||
using Tegra::Shader::Instruction;
|
||||
using Tegra::Shader::OpCode;
|
||||
using Tegra::Shader::Register;
|
||||
@ -42,6 +43,66 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) {
|
||||
SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b));
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::IADD3_C:
|
||||
case OpCode::Id::IADD3_R:
|
||||
case OpCode::Id::IADD3_IMM: {
|
||||
UNIMPLEMENTED_IF_MSG(instr.generates_cc,
|
||||
"Condition codes generation in IADD3 is not implemented");
|
||||
|
||||
Node op_c = GetRegister(instr.gpr39);
|
||||
|
||||
const auto ApplyHeight = [&](IAdd3Height height, Node value) {
|
||||
switch (height) {
|
||||
case IAdd3Height::None:
|
||||
return value;
|
||||
case IAdd3Height::LowerHalfWord:
|
||||
return Operation(OperationCode::IBitwiseAnd, NO_PRECISE, value, Immediate(0xffff));
|
||||
case IAdd3Height::UpperHalfWord:
|
||||
return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, value,
|
||||
Immediate(16));
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast<u32>(height));
|
||||
return Immediate(0);
|
||||
}
|
||||
};
|
||||
|
||||
if (opcode->get().GetId() == OpCode::Id::IADD3_R) {
|
||||
op_a = ApplyHeight(instr.iadd3.height_a, op_a);
|
||||
op_b = ApplyHeight(instr.iadd3.height_b, op_b);
|
||||
op_c = ApplyHeight(instr.iadd3.height_c, op_c);
|
||||
}
|
||||
|
||||
op_a = GetOperandAbsNegInteger(op_a, false, instr.iadd3.neg_a, true);
|
||||
op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true);
|
||||
op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true);
|
||||
|
||||
const Node value = [&]() {
|
||||
const Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b);
|
||||
if (opcode->get().GetId() != OpCode::Id::IADD3_R) {
|
||||
return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c);
|
||||
}
|
||||
const Node shifted = [&]() {
|
||||
switch (instr.iadd3.mode) {
|
||||
case Tegra::Shader::IAdd3Mode::RightShift:
|
||||
// TODO(tech4me): According to
|
||||
// https://envytools.readthedocs.io/en/latest/hw/graph/maxwell/cuda/int.html?highlight=iadd3
|
||||
// The addition between op_a and op_b should be done in uint33, more
|
||||
// investigation required
|
||||
return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, add_ab,
|
||||
Immediate(16));
|
||||
case Tegra::Shader::IAdd3Mode::LeftShift:
|
||||
return Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, add_ab,
|
||||
Immediate(16));
|
||||
default:
|
||||
return add_ab;
|
||||
}
|
||||
}();
|
||||
return Operation(OperationCode::IAdd, NO_PRECISE, shifted, op_c);
|
||||
}();
|
||||
|
||||
SetRegister(bb, instr.gpr0, value);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::ISCADD_C:
|
||||
case OpCode::Id::ISCADD_R:
|
||||
case OpCode::Id::ISCADD_IMM: {
|
||||
|
Loading…
Reference in New Issue
Block a user