forked from suyu/suyu
Merge pull request #1103 from Subv/lop_pred
Shader: Implemented the predicate and mode arguments of LOP.
This commit is contained in:
commit
d6cb22b0df
2 changed files with 39 additions and 11 deletions
|
@ -214,6 +214,11 @@ enum class FlowCondition : u64 {
|
||||||
Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
|
Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class PredicateResultMode : u64 {
|
||||||
|
None = 0x0,
|
||||||
|
NotZero = 0x3,
|
||||||
|
};
|
||||||
|
|
||||||
union Instruction {
|
union Instruction {
|
||||||
Instruction& operator=(const Instruction& instr) {
|
Instruction& operator=(const Instruction& instr) {
|
||||||
value = instr.value;
|
value = instr.value;
|
||||||
|
@ -254,7 +259,7 @@ union Instruction {
|
||||||
BitField<39, 1, u64> invert_a;
|
BitField<39, 1, u64> invert_a;
|
||||||
BitField<40, 1, u64> invert_b;
|
BitField<40, 1, u64> invert_b;
|
||||||
BitField<41, 2, LogicOperation> operation;
|
BitField<41, 2, LogicOperation> operation;
|
||||||
BitField<44, 2, u64> unk44;
|
BitField<44, 2, PredicateResultMode> pred_result_mode;
|
||||||
BitField<48, 3, Pred> pred48;
|
BitField<48, 3, Pred> pred48;
|
||||||
} lop;
|
} lop;
|
||||||
|
|
||||||
|
|
|
@ -756,28 +756,51 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteLogicOperation(Register dest, LogicOperation logic_op, const std::string& op_a,
|
void WriteLogicOperation(Register dest, LogicOperation logic_op, const std::string& op_a,
|
||||||
const std::string& op_b) {
|
const std::string& op_b,
|
||||||
|
Tegra::Shader::PredicateResultMode predicate_mode,
|
||||||
|
Tegra::Shader::Pred predicate) {
|
||||||
|
std::string result{};
|
||||||
switch (logic_op) {
|
switch (logic_op) {
|
||||||
case LogicOperation::And: {
|
case LogicOperation::And: {
|
||||||
regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " & " + op_b + ')', 1, 1);
|
result = '(' + op_a + " & " + op_b + ')';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LogicOperation::Or: {
|
case LogicOperation::Or: {
|
||||||
regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " | " + op_b + ')', 1, 1);
|
result = '(' + op_a + " | " + op_b + ')';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LogicOperation::Xor: {
|
case LogicOperation::Xor: {
|
||||||
regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " ^ " + op_b + ')', 1, 1);
|
result = '(' + op_a + " ^ " + op_b + ')';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LogicOperation::PassB: {
|
case LogicOperation::PassB: {
|
||||||
regs.SetRegisterToInteger(dest, true, 0, op_b, 1, 1);
|
result = op_b;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LOG_CRITICAL(HW_GPU, "Unimplemented logic operation: {}", static_cast<u32>(logic_op));
|
LOG_CRITICAL(HW_GPU, "Unimplemented logic operation: {}", static_cast<u32>(logic_op));
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dest != Tegra::Shader::Register::ZeroIndex) {
|
||||||
|
regs.SetRegisterToInteger(dest, true, 0, result, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
using Tegra::Shader::PredicateResultMode;
|
||||||
|
// Write the predicate value depending on the predicate mode.
|
||||||
|
switch (predicate_mode) {
|
||||||
|
case PredicateResultMode::None:
|
||||||
|
// Do nothing.
|
||||||
|
return;
|
||||||
|
case PredicateResultMode::NotZero:
|
||||||
|
// Set the predicate to true if the result is not zero.
|
||||||
|
SetPredicate(static_cast<u64>(predicate), '(' + result + ") != 0");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_CRITICAL(HW_GPU, "Unimplemented predicate result mode: {}",
|
||||||
|
static_cast<u32>(predicate_mode));
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteTexsInstruction(const Instruction& instr, const std::string& coord,
|
void WriteTexsInstruction(const Instruction& instr, const std::string& coord,
|
||||||
|
@ -1099,7 +1122,9 @@ private:
|
||||||
if (instr.alu.lop32i.invert_b)
|
if (instr.alu.lop32i.invert_b)
|
||||||
op_b = "~(" + op_b + ')';
|
op_b = "~(" + op_b + ')';
|
||||||
|
|
||||||
WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b);
|
WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b,
|
||||||
|
Tegra::Shader::PredicateResultMode::None,
|
||||||
|
Tegra::Shader::Pred::UnusedIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -1165,16 +1190,14 @@ private:
|
||||||
case OpCode::Id::LOP_C:
|
case OpCode::Id::LOP_C:
|
||||||
case OpCode::Id::LOP_R:
|
case OpCode::Id::LOP_R:
|
||||||
case OpCode::Id::LOP_IMM: {
|
case OpCode::Id::LOP_IMM: {
|
||||||
ASSERT_MSG(!instr.alu.lop.unk44, "Unimplemented");
|
|
||||||
ASSERT_MSG(instr.alu.lop.pred48 == Pred::UnusedIndex, "Unimplemented");
|
|
||||||
|
|
||||||
if (instr.alu.lop.invert_a)
|
if (instr.alu.lop.invert_a)
|
||||||
op_a = "~(" + op_a + ')';
|
op_a = "~(" + op_a + ')';
|
||||||
|
|
||||||
if (instr.alu.lop.invert_b)
|
if (instr.alu.lop.invert_b)
|
||||||
op_b = "~(" + op_b + ')';
|
op_b = "~(" + op_b + ')';
|
||||||
|
|
||||||
WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b);
|
WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b,
|
||||||
|
instr.alu.lop.pred_result_mode, instr.alu.lop.pred48);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::IMNMX_C:
|
case OpCode::Id::IMNMX_C:
|
||||||
|
|
Loading…
Reference in a new issue