shader/memory: Implement LDL.S16 and LDS.S16

This commit is contained in:
ReinUsesLisp 2020-01-25 03:15:55 -03:00
parent 05df4a8c94
commit 96638f57c9
1 changed files with 23 additions and 12 deletions

View File

@ -22,6 +22,7 @@ using Tegra::Shader::Attribute;
using Tegra::Shader::Instruction; using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode; using Tegra::Shader::OpCode;
using Tegra::Shader::Register; using Tegra::Shader::Register;
using Tegra::Shader::StoreType;
namespace { namespace {
@ -61,6 +62,13 @@ u32 GetMemorySize(Tegra::Shader::UniformType uniform_type) {
} }
} }
Node Sign16Extend(Node value) {
Node sign = Operation(OperationCode::UBitwiseAnd, value, Immediate(1U << 15));
Node is_sign = Operation(OperationCode::LogicalUEqual, std::move(sign), Immediate(1U << 15));
Node extend = Operation(OperationCode::Select, is_sign, Immediate(0xFFFF0000), Immediate(0));
return Operation(OperationCode::UBitwiseOr, std::move(value), std::move(extend));
}
} // Anonymous namespace } // Anonymous namespace
u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
@ -139,23 +147,26 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
const auto GetMemory = [&](s32 offset) { const auto GetMemory = [&](s32 offset) {
ASSERT(offset % 4 == 0); ASSERT(offset % 4 == 0);
const Node immediate_offset = Immediate(static_cast<s32>(instr.smem_imm) + offset); const Node immediate_offset = Immediate(static_cast<s32>(instr.smem_imm) + offset);
const Node address = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), const Node address =
immediate_offset); Operation(OperationCode::IAdd, GetRegister(instr.gpr8), immediate_offset);
return opcode->get().GetId() == OpCode::Id::LD_S ? GetSharedMemory(address) return opcode->get().GetId() == OpCode::Id::LD_S ? GetSharedMemory(address)
: GetLocalMemory(address); : GetLocalMemory(address);
}; };
switch (instr.ldst_sl.type.Value()) { switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bits32: case StoreType::Signed16:
case Tegra::Shader::StoreType::Bits64: SetRegister(bb, instr.gpr0, Sign16Extend(GetMemory(0)));
case Tegra::Shader::StoreType::Bits128: { break;
const u32 count = [&]() { case StoreType::Bits32:
case StoreType::Bits64:
case StoreType::Bits128: {
const u32 count = [&] {
switch (instr.ldst_sl.type.Value()) { switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bits32: case StoreType::Bits32:
return 1; return 1;
case Tegra::Shader::StoreType::Bits64: case StoreType::Bits64:
return 2; return 2;
case Tegra::Shader::StoreType::Bits128: case StoreType::Bits128:
return 4; return 4;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -274,14 +285,14 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
: &ShaderIR::SetSharedMemory; : &ShaderIR::SetSharedMemory;
switch (instr.ldst_sl.type.Value()) { switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bits128: case StoreType::Bits128:
(this->*set_memory)(bb, GetAddress(12), GetRegister(instr.gpr0.Value() + 3)); (this->*set_memory)(bb, GetAddress(12), GetRegister(instr.gpr0.Value() + 3));
(this->*set_memory)(bb, GetAddress(8), GetRegister(instr.gpr0.Value() + 2)); (this->*set_memory)(bb, GetAddress(8), GetRegister(instr.gpr0.Value() + 2));
[[fallthrough]]; [[fallthrough]];
case Tegra::Shader::StoreType::Bits64: case StoreType::Bits64:
(this->*set_memory)(bb, GetAddress(4), GetRegister(instr.gpr0.Value() + 1)); (this->*set_memory)(bb, GetAddress(4), GetRegister(instr.gpr0.Value() + 1));
[[fallthrough]]; [[fallthrough]];
case Tegra::Shader::StoreType::Bits32: case StoreType::Bits32:
(this->*set_memory)(bb, GetAddress(0), GetRegister(instr.gpr0)); (this->*set_memory)(bb, GetAddress(0), GetRegister(instr.gpr0));
break; break;
default: default: