mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-27 17:22:46 +01:00
shader: Implement CSET and CSETP
This commit is contained in:
parent
32b6c63485
commit
3b7fd3ad0f
6 changed files with 114 additions and 15 deletions
|
@ -63,6 +63,7 @@ add_library(shader_recompiler STATIC
|
||||||
frontend/maxwell/translate/impl/common_encoding.h
|
frontend/maxwell/translate/impl/common_encoding.h
|
||||||
frontend/maxwell/translate/impl/common_funcs.cpp
|
frontend/maxwell/translate/impl/common_funcs.cpp
|
||||||
frontend/maxwell/translate/impl/common_funcs.h
|
frontend/maxwell/translate/impl/common_funcs.h
|
||||||
|
frontend/maxwell/translate/impl/condition_code_set.cpp
|
||||||
frontend/maxwell/translate/impl/find_leading_one.cpp
|
frontend/maxwell/translate/impl/find_leading_one.cpp
|
||||||
frontend/maxwell/translate/impl/floating_point_add.cpp
|
frontend/maxwell/translate/impl/floating_point_add.cpp
|
||||||
frontend/maxwell/translate/impl/floating_point_compare.cpp
|
frontend/maxwell/translate/impl/floating_point_compare.cpp
|
||||||
|
|
|
@ -5,12 +5,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Shader::IR {
|
namespace Shader::IR {
|
||||||
|
|
||||||
enum class FlowTest {
|
enum class FlowTest : u64 {
|
||||||
F,
|
F,
|
||||||
LT,
|
LT,
|
||||||
EQ,
|
EQ,
|
||||||
|
|
|
@ -169,16 +169,62 @@ void IREmitter::SetOFlag(const U1& value) {
|
||||||
|
|
||||||
static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) {
|
static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) {
|
||||||
switch (flow_test) {
|
switch (flow_test) {
|
||||||
case FlowTest::T:
|
|
||||||
return ir.Imm1(true);
|
|
||||||
case FlowTest::F:
|
case FlowTest::F:
|
||||||
return ir.Imm1(false);
|
return ir.Imm1(false);
|
||||||
|
case FlowTest::LT:
|
||||||
|
return ir.LogicalXor(ir.LogicalAnd(ir.GetSFlag(), ir.LogicalNot(ir.GetZFlag())),
|
||||||
|
ir.GetOFlag());
|
||||||
case FlowTest::EQ:
|
case FlowTest::EQ:
|
||||||
// TODO: Test this
|
return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.GetZFlag());
|
||||||
return ir.GetZFlag();
|
case FlowTest::LE:
|
||||||
|
return ir.LogicalXor(ir.GetSFlag(), ir.LogicalOr(ir.GetZFlag(), ir.GetOFlag()));
|
||||||
|
case FlowTest::GT:
|
||||||
|
return ir.LogicalAnd(ir.LogicalXor(ir.LogicalNot(ir.GetSFlag()), ir.GetOFlag()),
|
||||||
|
ir.LogicalNot(ir.GetZFlag()));
|
||||||
case FlowTest::NE:
|
case FlowTest::NE:
|
||||||
// TODO: Test this
|
|
||||||
return ir.LogicalNot(ir.GetZFlag());
|
return ir.LogicalNot(ir.GetZFlag());
|
||||||
|
case FlowTest::GE:
|
||||||
|
return ir.LogicalNot(ir.LogicalXor(ir.GetSFlag(), ir.GetOFlag()));
|
||||||
|
case FlowTest::NUM:
|
||||||
|
return ir.LogicalOr(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag()));
|
||||||
|
case FlowTest::NaN:
|
||||||
|
return ir.LogicalAnd(ir.GetSFlag(), ir.GetZFlag());
|
||||||
|
case FlowTest::LTU:
|
||||||
|
return ir.LogicalXor(ir.GetSFlag(), ir.GetOFlag());
|
||||||
|
case FlowTest::EQU:
|
||||||
|
return ir.GetZFlag();
|
||||||
|
case FlowTest::LEU:
|
||||||
|
return ir.LogicalOr(ir.LogicalXor(ir.GetSFlag(), ir.GetOFlag()), ir.GetZFlag());
|
||||||
|
case FlowTest::GTU:
|
||||||
|
return ir.LogicalXor(ir.LogicalNot(ir.GetSFlag()),
|
||||||
|
ir.LogicalOr(ir.GetZFlag(), ir.GetOFlag()));
|
||||||
|
case FlowTest::NEU:
|
||||||
|
return ir.LogicalOr(ir.GetSFlag(), ir.LogicalNot(ir.GetZFlag()));
|
||||||
|
case FlowTest::GEU:
|
||||||
|
return ir.LogicalXor(ir.LogicalOr(ir.LogicalNot(ir.GetSFlag()), ir.GetZFlag()),
|
||||||
|
ir.GetOFlag());
|
||||||
|
case FlowTest::T:
|
||||||
|
return ir.Imm1(true);
|
||||||
|
case FlowTest::OFF:
|
||||||
|
return ir.LogicalNot(ir.GetOFlag());
|
||||||
|
case FlowTest::LO:
|
||||||
|
return ir.LogicalNot(ir.GetCFlag());
|
||||||
|
case FlowTest::SFF:
|
||||||
|
return ir.LogicalNot(ir.GetSFlag());
|
||||||
|
case FlowTest::LS:
|
||||||
|
return ir.LogicalOr(ir.GetZFlag(), ir.LogicalNot(ir.GetCFlag()));
|
||||||
|
case FlowTest::HI:
|
||||||
|
return ir.LogicalAnd(ir.GetCFlag(), ir.LogicalNot(ir.GetZFlag()));
|
||||||
|
case FlowTest::SFT:
|
||||||
|
return ir.GetSFlag();
|
||||||
|
case FlowTest::HS:
|
||||||
|
return ir.GetCFlag();
|
||||||
|
case FlowTest::OFT:
|
||||||
|
return ir.GetOFlag();
|
||||||
|
case FlowTest::RLE:
|
||||||
|
return ir.LogicalOr(ir.GetSFlag(), ir.GetZFlag());
|
||||||
|
case FlowTest::RGT:
|
||||||
|
return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag()));
|
||||||
default:
|
default:
|
||||||
throw NotImplementedException("Flow test {}", flow_test);
|
throw NotImplementedException("Flow test {}", flow_test);
|
||||||
}
|
}
|
||||||
|
@ -190,6 +236,10 @@ U1 IREmitter::Condition(IR::Condition cond) {
|
||||||
return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test));
|
return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U1 IREmitter::GetFlowTestResult(FlowTest test) {
|
||||||
|
return GetFlowTest(*this, test);
|
||||||
|
}
|
||||||
|
|
||||||
F32 IREmitter::GetAttribute(IR::Attribute attribute) {
|
F32 IREmitter::GetAttribute(IR::Attribute attribute) {
|
||||||
return Inst<F32>(Opcode::GetAttribute, attribute);
|
return Inst<F32>(Opcode::GetAttribute, attribute);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
void SetOFlag(const U1& value);
|
void SetOFlag(const U1& value);
|
||||||
|
|
||||||
[[nodiscard]] U1 Condition(IR::Condition cond);
|
[[nodiscard]] U1 Condition(IR::Condition cond);
|
||||||
|
[[nodiscard]] U1 GetFlowTestResult(FlowTest test);
|
||||||
|
|
||||||
[[nodiscard]] F32 GetAttribute(IR::Attribute attribute);
|
[[nodiscard]] F32 GetAttribute(IR::Attribute attribute);
|
||||||
void SetAttribute(IR::Attribute attribute, const F32& value);
|
void SetAttribute(IR::Attribute attribute, const F32& value);
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
|
||||||
|
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
||||||
|
|
||||||
|
namespace Shader::Maxwell {
|
||||||
|
|
||||||
|
void TranslatorVisitor::CSET(u64 insn) {
|
||||||
|
union {
|
||||||
|
u64 raw;
|
||||||
|
BitField<0, 8, IR::Reg> dest_reg;
|
||||||
|
BitField<8, 5, IR::FlowTest> cc_test;
|
||||||
|
BitField<39, 3, IR::Pred> bop_pred;
|
||||||
|
BitField<42, 1, u64> neg_bop_pred;
|
||||||
|
BitField<44, 1, u64> bf;
|
||||||
|
BitField<45, 2, BooleanOp> bop;
|
||||||
|
} const cset{insn};
|
||||||
|
|
||||||
|
const IR::U32 one_mask{ir.Imm32(-1)};
|
||||||
|
const IR::U32 fp_one{ir.Imm32(0x3f800000)};
|
||||||
|
const IR::U32 fail_result{ir.Imm32(0)};
|
||||||
|
const IR::U32 pass_result{cset.bf == 0 ? one_mask : fp_one};
|
||||||
|
const IR::U1 cc_test_result{ir.GetFlowTestResult(cset.cc_test)};
|
||||||
|
const IR::U1 bop_pred{ir.GetPred(cset.bop_pred, cset.neg_bop_pred != 0)};
|
||||||
|
const IR::U1 pred_result{PredicateCombine(ir, cc_test_result, bop_pred, cset.bop)};
|
||||||
|
const IR::U32 result{ir.Select(pred_result, pass_result, fail_result)};
|
||||||
|
X(cset.dest_reg, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TranslatorVisitor::CSETP(u64 insn) {
|
||||||
|
union {
|
||||||
|
u64 raw;
|
||||||
|
BitField<0, 3, IR::Pred> dest_pred_b;
|
||||||
|
BitField<3, 3, IR::Pred> dest_pred_a;
|
||||||
|
BitField<8, 5, IR::FlowTest> cc_test;
|
||||||
|
BitField<39, 3, IR::Pred> bop_pred;
|
||||||
|
BitField<42, 1, u64> neg_bop_pred;
|
||||||
|
BitField<45, 2, BooleanOp> bop;
|
||||||
|
} const csetp{insn};
|
||||||
|
|
||||||
|
const BooleanOp bop{csetp.bop};
|
||||||
|
const IR::U1 bop_pred{ir.GetPred(csetp.bop_pred, csetp.neg_bop_pred != 0)};
|
||||||
|
const IR::U1 cc_test_result{ir.GetFlowTestResult(csetp.cc_test)};
|
||||||
|
const IR::U1 result_a{PredicateCombine(ir, cc_test_result, bop_pred, bop)};
|
||||||
|
const IR::U1 result_b{PredicateCombine(ir, ir.LogicalNot(cc_test_result), bop_pred, bop)};
|
||||||
|
ir.SetPred(csetp.dest_pred_a, result_a);
|
||||||
|
ir.SetPred(csetp.dest_pred_b, result_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Maxwell
|
|
@ -85,14 +85,6 @@ void TranslatorVisitor::CS2R(u64) {
|
||||||
ThrowNotImplemented(Opcode::CS2R);
|
ThrowNotImplemented(Opcode::CS2R);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslatorVisitor::CSET(u64) {
|
|
||||||
ThrowNotImplemented(Opcode::CSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TranslatorVisitor::CSETP(u64) {
|
|
||||||
ThrowNotImplemented(Opcode::CSETP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TranslatorVisitor::DADD_reg(u64) {
|
void TranslatorVisitor::DADD_reg(u64) {
|
||||||
ThrowNotImplemented(Opcode::DADD_reg);
|
ThrowNotImplemented(Opcode::DADD_reg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue