shader_decode: implement ATOMS instr partial.

This commit is contained in:
Nguyen Dac Nam 2020-03-13 23:09:41 +07:00 committed by namkazy
parent a2cc80b605
commit 3dc09a6250

View file

@ -376,16 +376,20 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
} }
Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
Node value = Operation(OperationCode::AtomicAdd, std::move(gmem), GetRegister(instr.gpr20)); Node value =
Operation(OperationCode::AtomicIAdd, std::move(gmem), GetRegister(instr.gpr20));
SetRegister(bb, instr.gpr0, std::move(value)); SetRegister(bb, instr.gpr0, std::move(value));
break; break;
} }
case OpCode::Id::ATOMS: { case OpCode::Id::ATOMS: {
UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}", UNIMPLEMENTED_IF_MSG(instr.atoms.operation == AtomicOp::Inc ||
static_cast<int>(instr.atoms.operation.Value())); instr.atoms.operation == AtomicOp::Dec,
UNIMPLEMENTED_IF_MSG(instr.atoms.type != AtomicType::U32, "type={}", "operation={}", static_cast<int>(instr.atoms.operation.Value()));
static_cast<int>(instr.atoms.type.Value())); UNIMPLEMENTED_IF_MSG(instr.atoms.type == AtomicType::S64 ||
instr.atoms.type == AtomicType::U64,
"type={}", static_cast<int>(instr.atoms.type.Value()));
const bool is_signed =
instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64;
const s32 offset = instr.atoms.GetImmediateOffset(); const s32 offset = instr.atoms.GetImmediateOffset();
Node address = GetRegister(instr.gpr8); Node address = GetRegister(instr.gpr8);
address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset));
@ -393,7 +397,35 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
Node memory = GetSharedMemory(std::move(address)); Node memory = GetSharedMemory(std::move(address));
Node data = GetRegister(instr.gpr20); Node data = GetRegister(instr.gpr20);
Node value = Operation(OperationCode::AtomicAdd, std::move(memory), std::move(data)); Node value = [&]() {
switch (instr.atoms.operation) {
case AtomicOp::Add:
return SignedOperation(OperationCode::AtomicIAdd, is_signed, std::move(memory),
std::move(data));
case AtomicOp::Min:
return SignedOperation(OperationCode::AtomicIMin, is_signed, std::move(memory),
std::move(data));
case AtomicOp::Max:
return SignedOperation(OperationCode::AtomicIMax, is_signed, std::move(memory),
std::move(data));
case AtomicOp::And:
return SignedOperation(OperationCode::AtomicIAnd, is_signed, std::move(memory),
std::move(data));
case AtomicOp::Or:
return SignedOperation(OperationCode::AtomicIOr, is_signed, std::move(memory),
std::move(data));
case AtomicOp::Xor:
return SignedOperation(OperationCode::AtomicIXor, is_signed, std::move(memory),
std::move(data));
case AtomicOp::Exch:
return SignedOperation(OperationCode::AtomicIExchange, is_signed, std::move(memory),
std::move(data));
default:
UNREACHABLE();
return Immediate(0);
}
}();
SetRegister(bb, instr.gpr0, std::move(value)); SetRegister(bb, instr.gpr0, std::move(value));
break; break;
} }
@ -427,8 +459,8 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock&
const auto [base_address, index, offset] = const auto [base_address, index, offset] =
TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
ASSERT_OR_EXECUTE_MSG(base_address != nullptr, ASSERT_OR_EXECUTE_MSG(
{ return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); }, base_address != nullptr, { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
"Global memory tracking failed"); "Global memory tracking failed");
bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset)));