summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt5
-rw-r--r--src/common/assert.h5
-rw-r--r--src/common/math_util.h16
-rw-r--r--src/common/x64/xbyak_abi.h222
-rw-r--r--src/common/x64/xbyak_util.h47
-rw-r--r--src/core/file_sys/card_image.h13
-rw-r--r--src/core/hle/kernel/process.cpp1
-rw-r--r--src/core/hle/kernel/process.h1
-rw-r--r--src/core/hle/kernel/shared_memory.cpp22
-rw-r--r--src/core/hle/kernel/shared_memory.h48
-rw-r--r--src/core/hle/kernel/svc.cpp4
-rw-r--r--src/core/hle/service/am/am.cpp24
-rw-r--r--src/core/hle/service/am/applets/applets.cpp6
-rw-r--r--src/core/hle/service/am/applets/applets.h50
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp24
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h7
-rw-r--r--src/core/hle/service/ldr/ldr.cpp41
-rw-r--r--src/video_core/engines/maxwell_3d.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp632
19 files changed, 412 insertions, 765 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index eccd8f64a..895ee53f1 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -95,14 +95,9 @@ if(ARCHITECTURE_x86_64)
PRIVATE
x64/cpu_detect.cpp
x64/cpu_detect.h
- x64/xbyak_abi.h
- x64/xbyak_util.h
)
endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::boost fmt microprofile)
-if (ARCHITECTURE_x86_64)
- target_link_libraries(common PRIVATE xbyak)
-endif()
diff --git a/src/common/assert.h b/src/common/assert.h
index 0d4eddc19..6002f7ab1 100644
--- a/src/common/assert.h
+++ b/src/common/assert.h
@@ -52,5 +52,8 @@ __declspec(noinline, noreturn)
#define DEBUG_ASSERT_MSG(_a_, _desc_, ...)
#endif
-#define UNIMPLEMENTED() LOG_CRITICAL(Debug, "Unimplemented code!")
+#define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!")
#define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__)
+
+#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!")
+#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__)
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 343cdd902..94b4394c5 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -4,18 +4,12 @@
#pragma once
-#include <algorithm>
#include <cstdlib>
#include <type_traits>
namespace MathUtil {
-static constexpr float PI = 3.14159265f;
-
-inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1,
- unsigned length1) {
- return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1));
-}
+constexpr float PI = 3.14159265f;
template <class T>
struct Rectangle {
@@ -24,16 +18,16 @@ struct Rectangle {
T right{};
T bottom{};
- Rectangle() = default;
+ constexpr Rectangle() = default;
- Rectangle(T left, T top, T right, T bottom)
+ constexpr Rectangle(T left, T top, T right, T bottom)
: left(left), top(top), right(right), bottom(bottom) {}
T GetWidth() const {
- return std::abs(static_cast<typename std::make_signed<T>::type>(right - left));
+ return std::abs(static_cast<std::make_signed_t<T>>(right - left));
}
T GetHeight() const {
- return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top));
+ return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));
}
Rectangle<T> TranslateX(const T x) const {
return Rectangle{left + x, top, right + x, bottom};
diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h
deleted file mode 100644
index 636a5c0f9..000000000
--- a/src/common/x64/xbyak_abi.h
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <initializer_list>
-#include <xbyak.h>
-#include "common/assert.h"
-#include "common/bit_set.h"
-
-namespace Common::X64 {
-
-inline int RegToIndex(const Xbyak::Reg& reg) {
- using Kind = Xbyak::Reg::Kind;
- ASSERT_MSG((reg.getKind() & (Kind::REG | Kind::XMM)) != 0,
- "RegSet only support GPRs and XMM registers.");
- ASSERT_MSG(reg.getIdx() < 16, "RegSet only supports XXM0-15.");
- return reg.getIdx() + (reg.getKind() == Kind::REG ? 0 : 16);
-}
-
-inline Xbyak::Reg64 IndexToReg64(int reg_index) {
- ASSERT(reg_index < 16);
- return Xbyak::Reg64(reg_index);
-}
-
-inline Xbyak::Xmm IndexToXmm(int reg_index) {
- ASSERT(reg_index >= 16 && reg_index < 32);
- return Xbyak::Xmm(reg_index - 16);
-}
-
-inline Xbyak::Reg IndexToReg(int reg_index) {
- if (reg_index < 16) {
- return IndexToReg64(reg_index);
- } else {
- return IndexToXmm(reg_index);
- }
-}
-
-inline BitSet32 BuildRegSet(std::initializer_list<Xbyak::Reg> regs) {
- BitSet32 bits;
- for (const Xbyak::Reg& reg : regs) {
- bits[RegToIndex(reg)] = true;
- }
- return bits;
-}
-
-const BitSet32 ABI_ALL_GPRS(0x0000FFFF);
-const BitSet32 ABI_ALL_XMMS(0xFFFF0000);
-
-#ifdef _WIN32
-
-// Microsoft x64 ABI
-const Xbyak::Reg ABI_RETURN = Xbyak::util::rax;
-const Xbyak::Reg ABI_PARAM1 = Xbyak::util::rcx;
-const Xbyak::Reg ABI_PARAM2 = Xbyak::util::rdx;
-const Xbyak::Reg ABI_PARAM3 = Xbyak::util::r8;
-const Xbyak::Reg ABI_PARAM4 = Xbyak::util::r9;
-
-const BitSet32 ABI_ALL_CALLER_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rcx,
- Xbyak::util::rdx,
- Xbyak::util::r8,
- Xbyak::util::r9,
- Xbyak::util::r10,
- Xbyak::util::r11,
- // XMMs
- Xbyak::util::xmm0,
- Xbyak::util::xmm1,
- Xbyak::util::xmm2,
- Xbyak::util::xmm3,
- Xbyak::util::xmm4,
- Xbyak::util::xmm5,
-});
-
-const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rbx,
- Xbyak::util::rsi,
- Xbyak::util::rdi,
- Xbyak::util::rbp,
- Xbyak::util::r12,
- Xbyak::util::r13,
- Xbyak::util::r14,
- Xbyak::util::r15,
- // XMMs
- Xbyak::util::xmm6,
- Xbyak::util::xmm7,
- Xbyak::util::xmm8,
- Xbyak::util::xmm9,
- Xbyak::util::xmm10,
- Xbyak::util::xmm11,
- Xbyak::util::xmm12,
- Xbyak::util::xmm13,
- Xbyak::util::xmm14,
- Xbyak::util::xmm15,
-});
-
-constexpr std::size_t ABI_SHADOW_SPACE = 0x20;
-
-#else
-
-// System V x86-64 ABI
-const Xbyak::Reg ABI_RETURN = Xbyak::util::rax;
-const Xbyak::Reg ABI_PARAM1 = Xbyak::util::rdi;
-const Xbyak::Reg ABI_PARAM2 = Xbyak::util::rsi;
-const Xbyak::Reg ABI_PARAM3 = Xbyak::util::rdx;
-const Xbyak::Reg ABI_PARAM4 = Xbyak::util::rcx;
-
-const BitSet32 ABI_ALL_CALLER_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rcx,
- Xbyak::util::rdx,
- Xbyak::util::rdi,
- Xbyak::util::rsi,
- Xbyak::util::r8,
- Xbyak::util::r9,
- Xbyak::util::r10,
- Xbyak::util::r11,
- // XMMs
- Xbyak::util::xmm0,
- Xbyak::util::xmm1,
- Xbyak::util::xmm2,
- Xbyak::util::xmm3,
- Xbyak::util::xmm4,
- Xbyak::util::xmm5,
- Xbyak::util::xmm6,
- Xbyak::util::xmm7,
- Xbyak::util::xmm8,
- Xbyak::util::xmm9,
- Xbyak::util::xmm10,
- Xbyak::util::xmm11,
- Xbyak::util::xmm12,
- Xbyak::util::xmm13,
- Xbyak::util::xmm14,
- Xbyak::util::xmm15,
-});
-
-const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({
- // GPRs
- Xbyak::util::rbx,
- Xbyak::util::rbp,
- Xbyak::util::r12,
- Xbyak::util::r13,
- Xbyak::util::r14,
- Xbyak::util::r15,
-});
-
-constexpr std::size_t ABI_SHADOW_SPACE = 0;
-
-#endif
-
-inline void ABI_CalculateFrameSize(BitSet32 regs, std::size_t rsp_alignment,
- std::size_t needed_frame_size, s32* out_subtraction,
- s32* out_xmm_offset) {
- int count = (regs & ABI_ALL_GPRS).Count();
- rsp_alignment -= count * 8;
- std::size_t subtraction = 0;
- int xmm_count = (regs & ABI_ALL_XMMS).Count();
- if (xmm_count) {
- // If we have any XMMs to save, we must align the stack here.
- subtraction = rsp_alignment & 0xF;
- }
- subtraction += 0x10 * xmm_count;
- std::size_t xmm_base_subtraction = subtraction;
- subtraction += needed_frame_size;
- subtraction += ABI_SHADOW_SPACE;
- // Final alignment.
- rsp_alignment -= subtraction;
- subtraction += rsp_alignment & 0xF;
-
- *out_subtraction = (s32)subtraction;
- *out_xmm_offset = (s32)(subtraction - xmm_base_subtraction);
-}
-
-inline std::size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs,
- std::size_t rsp_alignment,
- std::size_t needed_frame_size = 0) {
- s32 subtraction, xmm_offset;
- ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset);
-
- for (int reg_index : (regs & ABI_ALL_GPRS)) {
- code.push(IndexToReg64(reg_index));
- }
-
- if (subtraction != 0) {
- code.sub(code.rsp, subtraction);
- }
-
- for (int reg_index : (regs & ABI_ALL_XMMS)) {
- code.movaps(code.xword[code.rsp + xmm_offset], IndexToXmm(reg_index));
- xmm_offset += 0x10;
- }
-
- return ABI_SHADOW_SPACE;
-}
-
-inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs,
- std::size_t rsp_alignment,
- std::size_t needed_frame_size = 0) {
- s32 subtraction, xmm_offset;
- ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset);
-
- for (int reg_index : (regs & ABI_ALL_XMMS)) {
- code.movaps(IndexToXmm(reg_index), code.xword[code.rsp + xmm_offset]);
- xmm_offset += 0x10;
- }
-
- if (subtraction != 0) {
- code.add(code.rsp, subtraction);
- }
-
- // GPRs need to be popped in reverse order
- for (int reg_index = 15; reg_index >= 0; reg_index--) {
- if (regs[reg_index]) {
- code.pop(IndexToReg64(reg_index));
- }
- }
-}
-
-} // namespace Common::X64
diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h
deleted file mode 100644
index 5cc8a8c76..000000000
--- a/src/common/x64/xbyak_util.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <type_traits>
-#include <xbyak.h>
-#include "common/x64/xbyak_abi.h"
-
-namespace Common::X64 {
-
-// Constants for use with cmpps/cmpss
-enum {
- CMP_EQ = 0,
- CMP_LT = 1,
- CMP_LE = 2,
- CMP_UNORD = 3,
- CMP_NEQ = 4,
- CMP_NLT = 5,
- CMP_NLE = 6,
- CMP_ORD = 7,
-};
-
-inline bool IsWithin2G(uintptr_t ref, uintptr_t target) {
- u64 distance = target - (ref + 5);
- return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL);
-}
-
-inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
- return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target);
-}
-
-template <typename T>
-inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
- static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
- std::size_t addr = reinterpret_cast<std::size_t>(f);
- if (IsWithin2G(code, addr)) {
- code.call(f);
- } else {
- // ABI_RETURN is a safe temp register to use before a call
- code.mov(ABI_RETURN, addr);
- code.call(ABI_RETURN);
- }
-}
-
-} // namespace Common::X64
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h
index 25f5914b6..a350496f7 100644
--- a/src/core/file_sys/card_image.h
+++ b/src/core/file_sys/card_image.h
@@ -32,7 +32,18 @@ enum class GamecardSize : u8 {
};
struct GamecardInfo {
- std::array<u8, 0x70> data;
+ u64_le firmware_version;
+ u32_le access_control_flags;
+ u32_le read_wait_time1;
+ u32_le read_wait_time2;
+ u32_le write_wait_time1;
+ u32_le write_wait_time2;
+ u32_le firmware_mode;
+ u32_le cup_version;
+ std::array<u8, 4> reserved1;
+ u64_le update_partition_hash;
+ u64_le cup_id;
+ std::array<u8, 0x38> reserved2;
};
static_assert(sizeof(GamecardInfo) == 0x70, "GamecardInfo has incorrect size.");
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 1412257a0..7ca538401 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <memory>
+#include <random>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 230e395ff..ada845c7f 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -8,7 +8,6 @@
#include <bitset>
#include <cstddef>
#include <memory>
-#include <random>
#include <string>
#include <vector>
#include <boost/container/static_vector.hpp>
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index a016a86b6..0494581f5 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -61,7 +61,7 @@ SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, SharedPtr<Proce
}
SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
- KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size,
+ KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, std::size_t offset, u64 size,
MemoryPermission permissions, MemoryPermission other_permissions, std::string name) {
SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));
@@ -78,10 +78,10 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
return shared_memory;
}
-ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
+ResultCode SharedMemory::Map(Process& target_process, VAddr address, MemoryPermission permissions,
MemoryPermission other_permissions) {
const MemoryPermission own_other_permissions =
- target_process == owner_process ? this->permissions : this->other_permissions;
+ &target_process == owner_process ? this->permissions : this->other_permissions;
// Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
@@ -106,7 +106,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
VAddr target_address = address;
// Map the memory block into the target process
- auto result = target_process->VMManager().MapMemoryBlock(
+ auto result = target_process.VMManager().MapMemoryBlock(
target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
if (result.Failed()) {
LOG_ERROR(
@@ -116,14 +116,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
return result.Code();
}
- return target_process->VMManager().ReprotectRange(target_address, size,
- ConvertPermissions(permissions));
+ return target_process.VMManager().ReprotectRange(target_address, size,
+ ConvertPermissions(permissions));
}
-ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) {
+ResultCode SharedMemory::Unmap(Process& target_process, VAddr address) {
// TODO(Subv): Verify what happens if the application tries to unmap an address that is not
// mapped to a SharedMemory.
- return target_process->VMManager().UnmapRange(address, size);
+ return target_process.VMManager().UnmapRange(address, size);
}
VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
@@ -132,7 +132,11 @@ VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
return static_cast<VMAPermission>(masked_permissions);
}
-u8* SharedMemory::GetPointer(u32 offset) {
+u8* SharedMemory::GetPointer(std::size_t offset) {
+ return backing_block->data() + backing_block_offset + offset;
+}
+
+const u8* SharedMemory::GetPointer(std::size_t offset) const {
return backing_block->data() + backing_block_offset + offset;
}
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 2c06bb7ce..0b48db699 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -64,7 +64,7 @@ public:
*/
static SharedPtr<SharedMemory> CreateForApplet(KernelCore& kernel,
std::shared_ptr<std::vector<u8>> heap_block,
- u32 offset, u32 size,
+ std::size_t offset, u64 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
std::string name = "Unknown Applet");
@@ -81,6 +81,11 @@ public:
return HANDLE_TYPE;
}
+ /// Gets the size of the underlying memory block in bytes.
+ u64 GetSize() const {
+ return size;
+ }
+
/**
* Converts the specified MemoryPermission into the equivalent VMAPermission.
* @param permission The MemoryPermission to convert.
@@ -94,44 +99,51 @@ public:
* @param permissions Memory block map permissions (specified by SVC field)
* @param other_permissions Memory block map other permissions (specified by SVC field)
*/
- ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions,
+ ResultCode Map(Process& target_process, VAddr address, MemoryPermission permissions,
MemoryPermission other_permissions);
/**
* Unmaps a shared memory block from the specified address in system memory
- * @param target_process Process from which to umap the memory block.
+ * @param target_process Process from which to unmap the memory block.
* @param address Address in system memory where the shared memory block is mapped
* @return Result code of the unmap operation
*/
- ResultCode Unmap(Process* target_process, VAddr address);
+ ResultCode Unmap(Process& target_process, VAddr address);
/**
* Gets a pointer to the shared memory block
* @param offset Offset from the start of the shared memory block to get pointer
- * @return Pointer to the shared memory block from the specified offset
+ * @return A pointer to the shared memory block from the specified offset
*/
- u8* GetPointer(u32 offset = 0);
+ u8* GetPointer(std::size_t offset = 0);
+
+ /**
+ * Gets a constant pointer to the shared memory block
+ * @param offset Offset from the start of the shared memory block to get pointer
+ * @return A constant pointer to the shared memory block from the specified offset
+ */
+ const u8* GetPointer(std::size_t offset = 0) const;
+
+private:
+ explicit SharedMemory(KernelCore& kernel);
+ ~SharedMemory() override;
- /// Process that created this shared memory block.
- SharedPtr<Process> owner_process;
- /// Address of shared memory block in the owner process if specified.
- VAddr base_address;
/// Backing memory for this shared memory block.
std::shared_ptr<std::vector<u8>> backing_block;
/// Offset into the backing block for this shared memory.
- std::size_t backing_block_offset;
+ std::size_t backing_block_offset = 0;
/// Size of the memory block. Page-aligned.
- u64 size;
+ u64 size = 0;
/// Permission restrictions applied to the process which created the block.
- MemoryPermission permissions;
+ MemoryPermission permissions{};
/// Permission restrictions applied to other processes mapping the block.
- MemoryPermission other_permissions;
+ MemoryPermission other_permissions{};
+ /// Process that created this shared memory block.
+ SharedPtr<Process> owner_process;
+ /// Address of shared memory block in the owner process if specified.
+ VAddr base_address = 0;
/// Name of shared memory object.
std::string name;
-
-private:
- explicit SharedMemory(KernelCore& kernel);
- ~SharedMemory() override;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 51c367de7..b8b6b4d49 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -789,7 +789,7 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return ERR_INVALID_MEMORY_RANGE;
}
- return shared_memory->Map(current_process, addr, permissions_type, MemoryPermission::DontCare);
+ return shared_memory->Map(*current_process, addr, permissions_type, MemoryPermission::DontCare);
}
static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
@@ -819,7 +819,7 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
return ERR_INVALID_MEMORY_RANGE;
}
- return shared_memory->Unmap(current_process, addr);
+ return shared_memory->Unmap(*current_process, addr);
}
/// Query process memory
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index fd14af1e7..11181a0af 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -532,8 +532,7 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
public:
explicit ILibraryAppletAccessor(std::shared_ptr<Applets::Applet> applet)
- : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)),
- broker(std::make_shared<Applets::AppletDataBroker>()) {
+ : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
@@ -562,7 +561,7 @@ public:
private:
void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) {
- const auto event = broker->GetStateChangedEvent();
+ const auto event = applet->GetBroker().GetStateChangedEvent();
event->Signal();
IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -590,7 +589,7 @@ private:
void Start(Kernel::HLERequestContext& ctx) {
ASSERT(applet != nullptr);
- applet->Initialize(broker);
+ applet->Initialize();
applet->Execute();
IPC::ResponseBuilder rb{ctx, 2};
@@ -601,7 +600,7 @@ private:
void PushInData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- broker->PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>());
+ applet->GetBroker().PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -612,7 +611,7 @@ private:
void PopOutData(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- const auto storage = broker->PopNormalDataToGame();
+ const auto storage = applet->GetBroker().PopNormalDataToGame();
if (storage == nullptr) {
rb.Push(ERR_NO_DATA_IN_CHANNEL);
return;
@@ -626,7 +625,7 @@ private:
void PushInteractiveInData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- broker->PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>());
+ applet->GetBroker().PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>());
ASSERT(applet->IsInitialized());
applet->ExecuteInteractive();
@@ -641,7 +640,7 @@ private:
void PopInteractiveOutData(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- const auto storage = broker->PopInteractiveDataToGame();
+ const auto storage = applet->GetBroker().PopInteractiveDataToGame();
if (storage == nullptr) {
rb.Push(ERR_NO_DATA_IN_CHANNEL);
return;
@@ -656,7 +655,7 @@ private:
void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
- rb.PushCopyObjects(broker->GetNormalDataEvent());
+ rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
LOG_DEBUG(Service_AM, "called");
}
@@ -664,13 +663,12 @@ private:
void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
- rb.PushCopyObjects(broker->GetInteractiveDataEvent());
+ rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
LOG_DEBUG(Service_AM, "called");
}
std::shared_ptr<Applets::Applet> applet;
- std::shared_ptr<Applets::AppletDataBroker> broker;
};
void IStorage::Open(Kernel::HLERequestContext& ctx) {
@@ -820,8 +818,8 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
return;
}
- const auto mem_begin = shared_mem->backing_block->begin() + shared_mem->backing_block_offset;
- const auto mem_end = mem_begin + shared_mem->size;
+ const u8* mem_begin = shared_mem->GetPointer();
+ const u8* mem_end = mem_begin + shared_mem->GetSize();
std::vector<u8> memory{mem_begin, mem_end};
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 8adb81823..becbadd06 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -98,10 +98,8 @@ Applet::Applet() = default;
Applet::~Applet() = default;
-void Applet::Initialize(std::shared_ptr<AppletDataBroker> broker_) {
- broker = std::move(broker_);
-
- const auto common = broker->PopNormalDataToApplet();
+void Applet::Initialize() {
+ const auto common = broker.PopNormalDataToApplet();
ASSERT(common != nullptr);
const auto common_data = common->GetData();
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 136445649..f65ea119c 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -4,14 +4,17 @@
#pragma once
-#include <functional>
#include <memory>
#include <queue>
#include "common/swap.h"
-#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/kernel.h"
union ResultCode;
+namespace Kernel {
+class Event;
+}
+
namespace Service::AM {
class IStorage;
@@ -43,19 +46,26 @@ public:
private:
// Queues are named from applet's perspective
- std::queue<std::unique_ptr<IStorage>>
- in_channel; // PopNormalDataToApplet and PushNormalDataFromGame
- std::queue<std::unique_ptr<IStorage>>
- out_channel; // PopNormalDataToGame and PushNormalDataFromApplet
- std::queue<std::unique_ptr<IStorage>>
- in_interactive_channel; // PopInteractiveDataToApplet and PushInteractiveDataFromGame
- std::queue<std::unique_ptr<IStorage>>
- out_interactive_channel; // PopInteractiveDataToGame and PushInteractiveDataFromApplet
+
+ // PopNormalDataToApplet and PushNormalDataFromGame
+ std::queue<std::unique_ptr<IStorage>> in_channel;
+
+ // PopNormalDataToGame and PushNormalDataFromApplet
+ std::queue<std::unique_ptr<IStorage>> out_channel;
+
+ // PopInteractiveDataToApplet and PushInteractiveDataFromGame
+ std::queue<std::unique_ptr<IStorage>> in_interactive_channel;
+
+ // PopInteractiveDataToGame and PushInteractiveDataFromApplet
+ std::queue<std::unique_ptr<IStorage>> out_interactive_channel;
Kernel::SharedPtr<Kernel::Event> state_changed_event;
- Kernel::SharedPtr<Kernel::Event> pop_out_data_event; // Signaled on PushNormalDataFromApplet
- Kernel::SharedPtr<Kernel::Event>
- pop_interactive_out_data_event; // Signaled on PushInteractiveDataFromApplet
+
+ // Signaled on PushNormalDataFromApplet
+ Kernel::SharedPtr<Kernel::Event> pop_out_data_event;
+
+ // Signaled on PushInteractiveDataFromApplet
+ Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event;
};
class Applet {
@@ -63,7 +73,7 @@ public:
Applet();
virtual ~Applet();
- virtual void Initialize(std::shared_ptr<AppletDataBroker> broker);
+ virtual void Initialize();
virtual bool TransactionComplete() const = 0;
virtual ResultCode GetStatus() const = 0;
@@ -74,6 +84,14 @@ public:
return initialized;
}
+ AppletDataBroker& GetBroker() {
+ return broker;
+ }
+
+ const AppletDataBroker& GetBroker() const {
+ return broker;
+ }
+
protected:
struct CommonArguments {
u32_le arguments_version;
@@ -85,8 +103,8 @@ protected:
};
static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
- CommonArguments common_args;
- std::shared_ptr<AppletDataBroker> broker;
+ CommonArguments common_args{};
+ AppletDataBroker broker;
bool initialized = false;
};
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index c4b76a515..981bdec51 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -42,21 +42,21 @@ SoftwareKeyboard::SoftwareKeyboard() = default;
SoftwareKeyboard::~SoftwareKeyboard() = default;
-void SoftwareKeyboard::Initialize(std::shared_ptr<AppletDataBroker> broker_) {
+void SoftwareKeyboard::Initialize() {
complete = false;
initial_text.clear();
final_data.clear();
- Applet::Initialize(std::move(broker_));
+ Applet::Initialize();
- const auto keyboard_config_storage = broker->PopNormalDataToApplet();
+ const auto keyboard_config_storage = broker.PopNormalDataToApplet();
ASSERT(keyboard_config_storage != nullptr);
const auto& keyboard_config = keyboard_config_storage->GetData();
ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
- const auto work_buffer_storage = broker->PopNormalDataToApplet();
+ const auto work_buffer_storage = broker.PopNormalDataToApplet();
ASSERT(work_buffer_storage != nullptr);
const auto& work_buffer = work_buffer_storage->GetData();
@@ -81,7 +81,7 @@ void SoftwareKeyboard::ExecuteInteractive() {
if (complete)
return;
- const auto storage = broker->PopInteractiveDataToApplet();
+ const auto storage = broker.PopInteractiveDataToApplet();
ASSERT(storage != nullptr);
const auto data = storage->GetData();
const auto status = static_cast<bool>(data[0]);
@@ -95,13 +95,13 @@ void SoftwareKeyboard::ExecuteInteractive() {
std::memcpy(string.data(), data.data() + 4, string.size() * 2);
frontend.SendTextCheckDialog(
Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
- [this] { broker->SignalStateChanged(); });
+ [this] { broker.SignalStateChanged(); });
}
}
void SoftwareKeyboard::Execute() {
if (complete) {
- broker->PushNormalDataFromApplet(IStorage{final_data});
+ broker.PushNormalDataFromApplet(IStorage{final_data});
return;
}
@@ -145,17 +145,17 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
final_data = output_main;
if (complete) {
- broker->PushNormalDataFromApplet(IStorage{output_main});
+ broker.PushNormalDataFromApplet(IStorage{output_main});
} else {
- broker->PushInteractiveDataFromApplet(IStorage{output_sub});
+ broker.PushInteractiveDataFromApplet(IStorage{output_sub});
}
- broker->SignalStateChanged();
+ broker.SignalStateChanged();
} else {
output_main[0] = 1;
complete = true;
- broker->PushNormalDataFromApplet(IStorage{output_main});
- broker->SignalStateChanged();
+ broker.PushNormalDataFromApplet(IStorage{output_main});
+ broker.SignalStateChanged();
}
}
} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index 16e1fff66..efd5753a1 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -4,7 +4,12 @@
#pragma once
+#include <array>
+#include <string>
+#include <vector>
+
#include "common/common_funcs.h"
+#include "common/swap.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h"
@@ -50,7 +55,7 @@ public:
SoftwareKeyboard();
~SoftwareKeyboard() override;
- void Initialize(std::shared_ptr<AppletDataBroker> broker) override;
+ void Initialize() override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index b43f1f054..7a9d0d0dd 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -16,35 +16,18 @@
namespace Service::LDR {
-namespace ErrCodes {
-enum {
- InvalidMemoryState = 51,
- InvalidNRO = 52,
- InvalidNRR = 53,
- MissingNRRHash = 54,
- MaximumNRO = 55,
- MaximumNRR = 56,
- AlreadyLoaded = 57,
- InvalidAlignment = 81,
- InvalidSize = 82,
- InvalidNROAddress = 84,
- InvalidNRRAddress = 85,
- NotInitialized = 87,
-};
-}
-
-constexpr ResultCode ERROR_INVALID_MEMORY_STATE(ErrorModule::Loader, ErrCodes::InvalidMemoryState);
-constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO);
-constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR);
-constexpr ResultCode ERROR_MISSING_NRR_HASH(ErrorModule::Loader, ErrCodes::MissingNRRHash);
-constexpr ResultCode ERROR_MAXIMUM_NRO(ErrorModule::Loader, ErrCodes::MaximumNRO);
-constexpr ResultCode ERROR_MAXIMUM_NRR(ErrorModule::Loader, ErrCodes::MaximumNRR);
-constexpr ResultCode ERROR_ALREADY_LOADED(ErrorModule::Loader, ErrCodes::AlreadyLoaded);
-constexpr ResultCode ERROR_INVALID_ALIGNMENT(ErrorModule::Loader, ErrCodes::InvalidAlignment);
-constexpr ResultCode ERROR_INVALID_SIZE(ErrorModule::Loader, ErrCodes::InvalidSize);
-constexpr ResultCode ERROR_INVALID_NRO_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNROAddress);
-constexpr ResultCode ERROR_INVALID_NRR_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNRRAddress);
-constexpr ResultCode ERROR_NOT_INITIALIZED(ErrorModule::Loader, ErrCodes::NotInitialized);
+constexpr ResultCode ERROR_INVALID_MEMORY_STATE{ErrorModule::Loader, 51};
+constexpr ResultCode ERROR_INVALID_NRO{ErrorModule::Loader, 52};
+constexpr ResultCode ERROR_INVALID_NRR{ErrorModule::Loader, 53};
+constexpr ResultCode ERROR_MISSING_NRR_HASH{ErrorModule::Loader, 54};
+constexpr ResultCode ERROR_MAXIMUM_NRO{ErrorModule::Loader, 55};
+constexpr ResultCode ERROR_MAXIMUM_NRR{ErrorModule::Loader, 56};
+constexpr ResultCode ERROR_ALREADY_LOADED{ErrorModule::Loader, 57};
+constexpr ResultCode ERROR_INVALID_ALIGNMENT{ErrorModule::Loader, 81};
+constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::Loader, 82};
+constexpr ResultCode ERROR_INVALID_NRO_ADDRESS{ErrorModule::Loader, 84};
+constexpr ResultCode ERROR_INVALID_NRR_ADDRESS{ErrorModule::Loader, 85};
+constexpr ResultCode ERROR_NOT_INITIALIZED{ErrorModule::Loader, 87};
constexpr u64 MAXIMUM_LOADED_RO = 0x40;
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index a04e00ecb..2bc534be3 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -69,6 +69,15 @@ void Maxwell3D::InitializeRegisterDefaults() {
// TODO(Rodrigo): Most games do not set a point size. I think this is a case of a
// register carrying a default value. Assume it's OpenGL's default (1).
regs.point_size = 1.0f;
+
+ // TODO(bunnei): Some games do not initialize the color masks (e.g. Sonic Mania). Assuming a
+ // default of enabled fixes rendering here.
+ for (std::size_t color_mask = 0; color_mask < Regs::NumRenderTargets; color_mask++) {
+ regs.color_mask[color_mask].R.Assign(1);
+ regs.color_mask[color_mask].G.Assign(1);
+ regs.color_mask[color_mask].B.Assign(1);
+ regs.color_mask[color_mask].A.Assign(1);
+ }
}
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 5fde22ad4..90a88b91a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -49,8 +49,7 @@ static std::string GetTopologyName(Tegra::Shader::OutputTopology topology) {
case Tegra::Shader::OutputTopology::TriangleStrip:
return "triangle_strip";
default:
- LOG_CRITICAL(Render_OpenGL, "Unknown output topology {}", static_cast<u32>(topology));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unknown output topology: {}", static_cast<u32>(topology));
return "points";
}
}
@@ -167,8 +166,8 @@ private:
case OpCode::Id::SSY:
case OpCode::Id::PBK: {
// The SSY and PBK use a similar encoding as the BRA instruction.
- ASSERT_MSG(instr.bra.constant_buffer == 0,
- "Constant buffer branching is not supported");
+ UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
+ "Constant buffer branching is not supported");
const u32 target = offset + instr.bra.GetBranchTarget();
labels.insert(target);
// Continue scanning for an exit method.
@@ -299,8 +298,7 @@ public:
// Default - do nothing
return value;
default:
- LOG_CRITICAL(HW_GPU, "Unimplemented conversion size {}", static_cast<u32>(size));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unimplemented conversion size: {}", static_cast<u32>(size));
}
}
@@ -363,7 +361,7 @@ public:
u64 value_num_components, bool is_saturated = false,
u64 dest_elem = 0, Register::Size size = Register::Size::Word,
bool sets_cc = false) {
- ASSERT_MSG(!is_saturated, "Unimplemented");
+ UNIMPLEMENTED_IF(is_saturated);
const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"};
@@ -392,7 +390,7 @@ public:
Tegra::Shader::HalfMerge merge, u64 dest_num_components,
u64 value_num_components, bool is_saturated = false,
u64 dest_elem = 0) {
- ASSERT_MSG(!is_saturated, "Unimplemented");
+ UNIMPLEMENTED_IF(is_saturated);
const std::string result = [&]() {
switch (merge) {
@@ -461,8 +459,7 @@ public:
case Tegra::Shader::ControlCode::NEU:
return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')';
default:
- LOG_CRITICAL(HW_GPU, "Unimplemented Control Code {}", static_cast<u32>(cc));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unimplemented Control Code: {}", static_cast<u32>(cc));
return "false";
}
}
@@ -761,8 +758,7 @@ private:
u64 dest_num_components, u64 value_num_components, u64 dest_elem,
bool precise) {
if (reg == Register::ZeroIndex) {
- LOG_CRITICAL(HW_GPU, "Cannot set Register::ZeroIndex");
- UNREACHABLE();
+ // Setting RZ is a nop in hardware.
return;
}
@@ -847,16 +843,13 @@ private:
if (declr_input_attribute.count(attribute) == 0) {
declr_input_attribute[attribute] = input_mode;
} else {
- if (declr_input_attribute[attribute] != input_mode) {
- LOG_CRITICAL(HW_GPU, "Same Input multiple input modes");
- UNREACHABLE();
- }
+ UNIMPLEMENTED_IF_MSG(declr_input_attribute[attribute] != input_mode,
+ "Multiple input modes for the same attribute");
}
return GeometryPass("input_attribute_" + std::to_string(index));
}
- LOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", static_cast<u32>(attribute));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
}
return "vec4(0, 0, 0, 0)";
@@ -882,24 +875,20 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled Ipa InterpMode: {}", static_cast<u32>(interp_mode));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled IPA interp mode: {}", static_cast<u32>(interp_mode));
}
}
switch (sample_mode) {
- case Tegra::Shader::IpaSampleMode::Centroid: {
- // Note not implemented, it can be implemented with the "centroid " keyword in glsl;
- LOG_CRITICAL(HW_GPU, "Ipa Sampler Mode: centroid, not implemented");
- UNREACHABLE();
+ case Tegra::Shader::IpaSampleMode::Centroid:
+ // It can be implemented with the "centroid " keyword in glsl
+ UNIMPLEMENTED_MSG("Unimplemented IPA sampler mode centroid");
break;
- }
- case Tegra::Shader::IpaSampleMode::Default: {
+ case Tegra::Shader::IpaSampleMode::Default:
// Default, n/a
break;
- }
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled Ipa SampleMode: {}", static_cast<u32>(sample_mode));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unimplemented IPA sampler mode: {}", static_cast<u32>(sample_mode));
+ break;
}
}
return out;
@@ -920,8 +909,7 @@ private:
return "output_attribute_" + std::to_string(index);
}
- LOG_CRITICAL(HW_GPU, "Unhandled output attribute: {}", index);
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled output attribute={}", index);
return {};
}
}
@@ -1078,8 +1066,8 @@ private:
{PredCondition::GreaterThanWithNan, ">"}, {PredCondition::GreaterEqualWithNan, ">="}};
const auto& comparison{PredicateComparisonStrings.find(condition)};
- ASSERT_MSG(comparison != PredicateComparisonStrings.end(),
- "Unknown predicate comparison operation");
+ UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonStrings.end(),
+ "Unknown predicate comparison operation");
std::string predicate{'(' + op_a + ") " + comparison->second + " (" + op_b + ')'};
if (condition == PredCondition::LessThanWithNan ||
@@ -1107,7 +1095,7 @@ private:
};
auto op = PredicateOperationStrings.find(operation);
- ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation");
+ UNIMPLEMENTED_IF_MSG(op == PredicateOperationStrings.end(), "Unknown predicate operation");
return op->second;
}
@@ -1205,8 +1193,7 @@ private:
break;
}
default:
- LOG_CRITICAL(HW_GPU, "Unimplemented logic operation: {}", static_cast<u32>(logic_op));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unimplemented logic operation={}", static_cast<u32>(logic_op));
}
if (dest != Tegra::Shader::Register::ZeroIndex) {
@@ -1224,9 +1211,8 @@ private:
SetPredicate(static_cast<u64>(predicate), '(' + result + ") != 0");
break;
default:
- LOG_CRITICAL(HW_GPU, "Unimplemented predicate result mode: {}",
- static_cast<u32>(predicate_mode));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unimplemented predicate result mode: {}",
+ static_cast<u32>(predicate_mode));
}
}
@@ -1294,19 +1280,15 @@ private:
static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) {
switch (texture_type) {
- case Tegra::Shader::TextureType::Texture1D: {
+ case Tegra::Shader::TextureType::Texture1D:
return 1;
- }
- case Tegra::Shader::TextureType::Texture2D: {
+ case Tegra::Shader::TextureType::Texture2D:
return 2;
- }
case Tegra::Shader::TextureType::Texture3D:
- case Tegra::Shader::TextureType::TextureCube: {
+ case Tegra::Shader::TextureType::TextureCube:
return 3;
- }
default:
- LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", static_cast<u32>(texture_type));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled texture type: {}", static_cast<u32>(texture_type));
return 0;
}
}
@@ -1342,7 +1324,7 @@ private:
void EmitFragmentOutputsWrite() {
ASSERT(stage == Maxwell3D::Regs::ShaderStage::Fragment);
- ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented");
+ UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Samplemask write is unimplemented");
shader.AddLine("if (alpha_test[0] != 0) {");
++shader.scope;
@@ -1408,7 +1390,7 @@ private:
case Tegra::Shader::VideoType::Size32:
// TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when
// this type is used (1 * 1 + 0 == 0x5b800000). Until a better
- // explanation is found: assert.
+ // explanation is found: abort.
UNIMPLEMENTED();
return zero;
case Tegra::Shader::VideoType::Invalid:
@@ -1464,8 +1446,7 @@ private:
// Decoding failure
if (!opcode) {
- LOG_CRITICAL(HW_GPU, "Unhandled instruction: {0:x}", instr.value);
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled instruction: {0:x}", instr.value);
return offset + 1;
}
@@ -1473,8 +1454,8 @@ private:
fmt::format("// {}: {} (0x{:016x})", offset, opcode->get().GetName(), instr.value));
using Tegra::Shader::Pred;
- ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
- "NeverExecute predicate not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.pred.full_pred == Pred::NeverExecute,
+ "NeverExecute predicate not implemented");
// Some instructions (like SSY) don't have a predicate field, they are always
// unconditionally executed.
@@ -1517,37 +1498,37 @@ private:
case OpCode::Id::FMUL_R:
case OpCode::Id::FMUL_IMM: {
// FMUL does not have 'abs' bits and only the second operand has a 'neg' bit.
- ASSERT_MSG(instr.fmul.tab5cb8_2 == 0, "FMUL tab5cb8_2({}) is not implemented",
- instr.fmul.tab5cb8_2.Value());
- ASSERT_MSG(instr.fmul.tab5c68_1 == 0, "FMUL tab5cb8_1({}) is not implemented",
- instr.fmul.tab5c68_1.Value());
- ASSERT_MSG(instr.fmul.tab5c68_0 == 1, "FMUL tab5cb8_0({}) is not implemented",
- instr.fmul.tab5c68_0
- .Value()); // SMO typical sends 1 here which seems to be the default
- ASSERT_MSG(instr.fmul.cc == 0, "FMUL cc is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.fmul.tab5cb8_2 != 0,
+ "FMUL tab5cb8_2({}) is not implemented",
+ instr.fmul.tab5cb8_2.Value());
+ UNIMPLEMENTED_IF_MSG(instr.fmul.tab5c68_1 != 0,
+ "FMUL tab5cb8_1({}) is not implemented",
+ instr.fmul.tab5c68_1.Value());
+ UNIMPLEMENTED_IF_MSG(
+ instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented",
+ instr.fmul.tab5c68_0
+ .Value()); // SMO typical sends 1 here which seems to be the default
+ UNIMPLEMENTED_IF_MSG(instr.fmul.cc != 0, "FMUL cc is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "FMUL Generates an unhandled Control Code");
op_b = GetOperandAbsNeg(op_b, false, instr.fmul.negate_b);
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1,
instr.alu.saturate_d, 0, true);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "FMUL Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::FADD_C:
case OpCode::Id::FADD_R:
case OpCode::Id::FADD_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "FADD Generates an unhandled Control Code");
+
op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1,
instr.alu.saturate_d, 0, true);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "FADD Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::MUFU: {
@@ -1582,15 +1563,17 @@ private:
instr.alu.saturate_d, 0, true);
break;
default:
- LOG_CRITICAL(HW_GPU, "Unhandled MUFU sub op: {0:x}",
- static_cast<unsigned>(instr.sub_op.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled MUFU sub op={0:x}",
+ static_cast<unsigned>(instr.sub_op.Value()));
}
break;
}
case OpCode::Id::FMNMX_C:
case OpCode::Id::FMNMX_R:
case OpCode::Id::FMNMX_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "FMNMX Generates an unhandled Control Code");
+
op_a = GetOperandAbsNeg(op_a, instr.alu.abs_a, instr.alu.negate_a);
op_b = GetOperandAbsNeg(op_b, instr.alu.abs_b, instr.alu.negate_b);
@@ -1601,10 +1584,6 @@ private:
'(' + condition + ") ? min(" + parameters + ") : max(" +
parameters + ')',
1, 1, false, 0, true);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "FMNMX Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::RRO_C:
@@ -1617,9 +1596,7 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {}",
- opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName());
}
}
break;
@@ -1631,17 +1608,19 @@ private:
break;
}
case OpCode::Id::FMUL32_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc,
+ "FMUL32 Generates an unhandled Control Code");
+
regs.SetRegisterToFloat(instr.gpr0, 0,
regs.GetRegisterAsFloat(instr.gpr8) + " * " +
GetImmediate32(instr),
1, 1, instr.fmul32.saturate, 0, true);
- if (instr.op_32.generates_cc) {
- LOG_CRITICAL(HW_GPU, "FMUL32 Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::FADD32I: {
+ UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc,
+ "FADD32 Generates an unhandled Control Code");
+
std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
std::string op_b = GetImmediate32(instr);
@@ -1662,23 +1641,21 @@ private:
}
regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, false, 0, true);
- if (instr.op_32.generates_cc) {
- LOG_CRITICAL(HW_GPU, "FADD32 Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
}
break;
}
case OpCode::Type::Bfe: {
- ASSERT_MSG(!instr.bfe.negate_b, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.bfe.negate_b);
std::string op_a = instr.bfe.negate_a ? "-" : "";
op_a += regs.GetRegisterAsInteger(instr.gpr8);
switch (opcode->get().GetId()) {
case OpCode::Id::BFE_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "BFE Generates an unhandled Control Code");
+
std::string inner_shift =
'(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')';
std::string outer_shift =
@@ -1686,15 +1663,10 @@ private:
std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')';
regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "BFE Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled BFE instruction: {}", opcode->get().GetName());
}
}
@@ -1719,6 +1691,8 @@ private:
case OpCode::Id::SHR_C:
case OpCode::Id::SHR_R:
case OpCode::Id::SHR_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "SHR Generates an unhandled Control Code");
+
if (!instr.shift.is_signed) {
// Logical shift right
op_a = "uint(" + op_a + ')';
@@ -1727,24 +1701,17 @@ private:
// Cast to int is superfluous for arithmetic shift, it's only for a logical shift
regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(" + op_a + " >> " + op_b + ')',
1, 1);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "SHR Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::SHL_C:
case OpCode::Id::SHL_R:
case OpCode::Id::SHL_IMM:
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "SHL Generates an unhandled Control Code");
+
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "SHL Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled shift instruction: {}", opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled shift instruction: {}", opcode->get().GetName());
}
}
break;
@@ -1755,17 +1722,19 @@ private:
switch (opcode->get().GetId()) {
case OpCode::Id::IADD32I:
+ UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc,
+ "IADD32 Generates an unhandled Control Code");
+
if (instr.iadd32i.negate_a)
op_a = "-(" + op_a + ')';
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1,
instr.iadd32i.saturate != 0);
- if (instr.op_32.generates_cc) {
- LOG_CRITICAL(HW_GPU, "IADD32 Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
case OpCode::Id::LOP32I: {
+ UNIMPLEMENTED_IF_MSG(instr.op_32.generates_cc,
+ "LOP32I Generates an unhandled Control Code");
+
if (instr.alu.lop32i.invert_a)
op_a = "~(" + op_a + ')';
@@ -1775,16 +1744,11 @@ private:
WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b,
Tegra::Shader::PredicateResultMode::None,
Tegra::Shader::Pred::UnusedIndex);
- if (instr.op_32.generates_cc) {
- LOG_CRITICAL(HW_GPU, "LOP32I Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}",
- opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled ArithmeticIntegerImmediate instruction: {}",
+ opcode->get().GetName());
}
}
break;
@@ -1807,6 +1771,9 @@ private:
case OpCode::Id::IADD_C:
case OpCode::Id::IADD_R:
case OpCode::Id::IADD_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "IADD Generates an unhandled Control Code");
+
if (instr.alu_integer.negate_a)
op_a = "-(" + op_a + ')';
@@ -1815,15 +1782,14 @@ private:
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1,
instr.alu.saturate_d);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "IADD Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::IADD3_C:
case OpCode::Id::IADD3_R:
case OpCode::Id::IADD3_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "IADD3 Generates an unhandled Control Code");
+
std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
auto apply_height = [](auto height, auto& oprand) {
@@ -1837,9 +1803,8 @@ private:
oprand = "((" + oprand + ") >> 16)";
break;
default:
- LOG_CRITICAL(HW_GPU, "Unhandled IADD3 height: {}",
- static_cast<u32>(height.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}",
+ static_cast<u32>(height.Value()));
}
};
@@ -1880,16 +1845,14 @@ private:
}
regs.SetRegisterToInteger(instr.gpr0, true, 0, result, 1, 1);
-
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "IADD3 Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::ISCADD_C:
case OpCode::Id::ISCADD_R:
case OpCode::Id::ISCADD_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "ISCADD Generates an unhandled Control Code");
+
if (instr.alu_integer.negate_a)
op_a = "-(" + op_a + ')';
@@ -1900,10 +1863,6 @@ private:
regs.SetRegisterToInteger(instr.gpr0, true, 0,
"((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "ISCADD Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::POPC_C:
@@ -1927,6 +1886,8 @@ private:
case OpCode::Id::LOP_C:
case OpCode::Id::LOP_R:
case OpCode::Id::LOP_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "LOP Generates an unhandled Control Code");
+
if (instr.alu.lop.invert_a)
op_a = "~(" + op_a + ')';
@@ -1935,15 +1896,14 @@ private:
WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b,
instr.alu.lop.pred_result_mode, instr.alu.lop.pred48);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "LOP Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::LOP3_C:
case OpCode::Id::LOP3_R:
case OpCode::Id::LOP3_IMM: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "LOP3 Generates an unhandled Control Code");
+
const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
std::string lut;
@@ -1954,17 +1914,15 @@ private:
}
WriteLop3Instruction(instr.gpr0, op_a, op_b, op_c, lut);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "LOP3 Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::IMNMX_C:
case OpCode::Id::IMNMX_R:
case OpCode::Id::IMNMX_IMM: {
- ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None,
- "Unimplemented");
+ UNIMPLEMENTED_IF(instr.imnmx.exchange != Tegra::Shader::IMinMaxExchange::None);
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+ "IMNMX Generates an unhandled Control Code");
+
const std::string condition =
GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0);
const std::string parameters = op_a + ',' + op_b;
@@ -1972,10 +1930,6 @@ private:
'(' + condition + ") ? min(" + parameters + ") : max(" +
parameters + ')',
1, 1);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "IMNMX Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::LEA_R2:
@@ -2030,24 +1984,19 @@ private:
op_b = regs.GetRegisterAsInteger(instr.gpr8);
op_a = std::to_string(instr.lea.imm.entry_a);
op_c = std::to_string(instr.lea.imm.entry_b);
- LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}",
- opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled LEA subinstruction: {}", opcode->get().GetName());
}
}
- if (instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex)) {
- LOG_ERROR(HW_GPU, "Unhandled LEA Predicate");
- UNREACHABLE();
- }
+ UNIMPLEMENTED_IF_MSG(instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex),
+ "Unhandled LEA Predicate");
const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))";
regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1);
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
- opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled ArithmeticInteger instruction: {}",
+ opcode->get().GetName());
}
}
@@ -2056,7 +2005,7 @@ private:
case OpCode::Type::ArithmeticHalf: {
if (opcode->get().GetId() == OpCode::Id::HADD2_C ||
opcode->get().GetId() == OpCode::Id::HADD2_R) {
- ASSERT_MSG(instr.alu_half.ftz == 0, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.alu_half.ftz != 0);
}
const bool negate_a =
opcode->get().GetId() != OpCode::Id::HMUL2_R && instr.alu_half.negate_a != 0;
@@ -2094,9 +2043,8 @@ private:
case OpCode::Id::HMUL2_R:
return '(' + op_a + " * " + op_b + ')';
default:
- LOG_CRITICAL(HW_GPU, "Unhandled half float instruction: {}",
- opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled half float instruction: {}",
+ opcode->get().GetName());
return std::string("0");
}
}();
@@ -2107,10 +2055,10 @@ private:
}
case OpCode::Type::ArithmeticHalfImmediate: {
if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) {
- ASSERT_MSG(instr.alu_half_imm.ftz == 0, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.alu_half_imm.ftz != 0);
} else {
- ASSERT_MSG(instr.alu_half_imm.precision == Tegra::Shader::HalfPrecision::None,
- "Unimplemented");
+ UNIMPLEMENTED_IF(instr.alu_half_imm.precision !=
+ Tegra::Shader::HalfPrecision::None);
}
const std::string op_a = GetHalfFloat(
@@ -2140,11 +2088,13 @@ private:
std::string op_b = instr.ffma.negate_b ? "-" : "";
std::string op_c = instr.ffma.negate_c ? "-" : "";
- ASSERT_MSG(instr.ffma.cc == 0, "FFMA cc not implemented");
- ASSERT_MSG(instr.ffma.tab5980_0 == 1, "FFMA tab5980_0({}) not implemented",
- instr.ffma.tab5980_0.Value()); // Seems to be 1 by default based on SMO
- ASSERT_MSG(instr.ffma.tab5980_1 == 0, "FFMA tab5980_1({}) not implemented",
- instr.ffma.tab5980_1.Value());
+ UNIMPLEMENTED_IF_MSG(instr.ffma.cc != 0, "FFMA cc not implemented");
+ UNIMPLEMENTED_IF_MSG(
+ instr.ffma.tab5980_0 != 1, "FFMA tab5980_0({}) not implemented",
+ instr.ffma.tab5980_0.Value()); // Seems to be 1 by default based on SMO
+ UNIMPLEMENTED_IF_MSG(instr.ffma.tab5980_1 != 0, "FFMA tab5980_1({}) not implemented",
+ instr.ffma.tab5980_1.Value());
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "FFMA Generates an unhandled Control Code");
switch (opcode->get().GetId()) {
case OpCode::Id::FFMA_CR: {
@@ -2170,27 +2120,19 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {}", opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled FFMA instruction: {}", opcode->get().GetName());
}
}
regs.SetRegisterToFloat(instr.gpr0, 0, "fma(" + op_a + ", " + op_b + ", " + op_c + ')',
1, 1, instr.alu.saturate_d, 0, true);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "FFMA Generates an unhandled Control Code");
- UNREACHABLE();
- }
-
break;
}
case OpCode::Type::Hfma2: {
if (opcode->get().GetId() == OpCode::Id::HFMA2_RR) {
- ASSERT_MSG(instr.hfma2.rr.precision == Tegra::Shader::HalfPrecision::None,
- "Unimplemented");
+ UNIMPLEMENTED_IF(instr.hfma2.rr.precision != Tegra::Shader::HalfPrecision::None);
} else {
- ASSERT_MSG(instr.hfma2.precision == Tegra::Shader::HalfPrecision::None,
- "Unimplemented");
+ UNIMPLEMENTED_IF(instr.hfma2.precision != Tegra::Shader::HalfPrecision::None);
}
const bool saturate = opcode->get().GetId() == OpCode::Id::HFMA2_RR
? instr.hfma2.rr.saturate != 0
@@ -2240,7 +2182,7 @@ private:
case OpCode::Type::Conversion: {
switch (opcode->get().GetId()) {
case OpCode::Id::I2I_R: {
- ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.conversion.selector);
std::string op_a = regs.GetRegisterAsInteger(
instr.gpr20, 0, instr.conversion.is_input_signed, instr.conversion.src_size);
@@ -2260,8 +2202,9 @@ private:
}
case OpCode::Id::I2F_R:
case OpCode::Id::I2F_C: {
- ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented");
- ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word);
+ UNIMPLEMENTED_IF(instr.conversion.selector);
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "I2F Generates an unhandled Control Code");
std::string op_a{};
@@ -2286,16 +2229,12 @@ private:
}
regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
-
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "I2F Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::F2F_R: {
- ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented");
- ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word);
+ UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word);
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "F2F Generates an unhandled Control Code");
std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
if (instr.conversion.abs_a) {
@@ -2322,23 +2261,18 @@ private:
op_a = "trunc(" + op_a + ')';
break;
default:
- LOG_CRITICAL(HW_GPU, "Unimplemented f2f rounding mode {}",
- static_cast<u32>(instr.conversion.f2f.rounding.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unimplemented F2F rounding mode {}",
+ static_cast<u32>(instr.conversion.f2f.rounding.Value()));
break;
}
regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1, instr.alu.saturate_d);
-
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "F2F Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
case OpCode::Id::F2I_R:
case OpCode::Id::F2I_C: {
- ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word);
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "F2I Generates an unhandled Control Code");
std::string op_a{};
if (instr.is_b_gpr) {
@@ -2369,9 +2303,8 @@ private:
op_a = "trunc(" + op_a + ')';
break;
default:
- LOG_CRITICAL(HW_GPU, "Unimplemented f2i rounding mode {}",
- static_cast<u32>(instr.conversion.f2i.rounding.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unimplemented F2I rounding mode {}",
+ static_cast<u32>(instr.conversion.f2i.rounding.Value()));
break;
}
@@ -2383,16 +2316,10 @@ private:
regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1,
1, false, 0, instr.conversion.dest_size);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "F2I Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}",
- opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled conversion instruction: {}", opcode->get().GetName());
}
}
break;
@@ -2401,10 +2328,10 @@ private:
switch (opcode->get().GetId()) {
case OpCode::Id::LD_A: {
// Note: Shouldn't this be interp mode flat? As in no interpolation made.
- ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex,
- "Indirect attribute loads are not supported");
- ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0,
- "Unaligned attribute loads are not supported");
+ UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex,
+ "Indirect attribute loads are not supported");
+ UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0,
+ "Unaligned attribute loads are not supported");
Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective,
Tegra::Shader::IpaSampleMode::Default};
@@ -2431,7 +2358,7 @@ private:
break;
}
case OpCode::Id::LD_C: {
- ASSERT_MSG(instr.ld_c.unknown == 0, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.ld_c.unknown != 0);
// Add an extra scope and declare the index register inside to prevent
// overwriting it in case it is used as an output of the LD instruction.
@@ -2459,9 +2386,8 @@ private:
break;
}
default:
- LOG_CRITICAL(HW_GPU, "Unhandled type: {}",
- static_cast<unsigned>(instr.ld_c.type.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled type: {}",
+ static_cast<unsigned>(instr.ld_c.type.Value()));
}
--shader.scope;
@@ -2469,6 +2395,9 @@ private:
break;
}
case OpCode::Id::LD_L: {
+ UNIMPLEMENTED_IF_MSG(instr.ld_l.unknown == 1, "LD_L Unhandled mode: {}",
+ static_cast<unsigned>(instr.ld_l.unknown.Value()));
+
// Add an extra scope and declare the index register inside to prevent
// overwriting it in case it is used as an output of the LD instruction.
shader.AddLine('{');
@@ -2481,20 +2410,13 @@ private:
const std::string op_a = regs.GetLocalMemoryAsFloat("index");
- if (instr.ld_l.unknown != 1) {
- LOG_CRITICAL(HW_GPU, "LD_L Unhandled mode: {}",
- static_cast<unsigned>(instr.ld_l.unknown.Value()));
- UNREACHABLE();
- }
-
switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bytes32:
regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
break;
default:
- LOG_CRITICAL(HW_GPU, "LD_L Unhandled type: {}",
- static_cast<unsigned>(instr.ldst_sl.type.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("LD_L Unhandled type: {}",
+ static_cast<unsigned>(instr.ldst_sl.type.Value()));
}
--shader.scope;
@@ -2502,10 +2424,10 @@ private:
break;
}
case OpCode::Id::ST_A: {
- ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex,
- "Indirect attribute loads are not supported");
- ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0,
- "Unaligned attribute loads are not supported");
+ UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex,
+ "Indirect attribute loads are not supported");
+ UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0,
+ "Unaligned attribute loads are not supported");
u64 next_element = instr.attribute.fmt20.element;
u64 next_index = static_cast<u64>(instr.attribute.fmt20.index.Value());
@@ -2530,6 +2452,9 @@ private:
break;
}
case OpCode::Id::ST_L: {
+ UNIMPLEMENTED_IF_MSG(instr.st_l.unknown == 0, "ST_L Unhandled mode: {}",
+ static_cast<unsigned>(instr.st_l.unknown.Value()));
+
// Add an extra scope and declare the index register inside to prevent
// overwriting it in case it is used as an output of the LD instruction.
shader.AddLine('{');
@@ -2540,20 +2465,13 @@ private:
shader.AddLine("uint index = (" + op + " / 4);");
- if (instr.st_l.unknown != 0) {
- LOG_CRITICAL(HW_GPU, "ST_L Unhandled mode: {}",
- static_cast<unsigned>(instr.st_l.unknown.Value()));
- UNREACHABLE();
- }
-
switch (instr.ldst_sl.type.Value()) {
case Tegra::Shader::StoreType::Bytes32:
regs.SetLocalMemoryAsFloat("index", regs.GetRegisterAsFloat(instr.gpr0));
break;
default:
- LOG_CRITICAL(HW_GPU, "ST_L Unhandled type: {}",
- static_cast<unsigned>(instr.ldst_sl.type.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("ST_L Unhandled type: {}",
+ static_cast<unsigned>(instr.ldst_sl.type.Value()));
}
--shader.scope;
@@ -2565,10 +2483,10 @@ private:
std::string coord;
const bool is_array = instr.tex.array != 0;
- ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
- "NODEP is not implemented");
- ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
- "AOFFI is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
+ "NODEP is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
+ "AOFFI is not implemented");
const bool depth_compare =
instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
@@ -2634,9 +2552,8 @@ private:
break;
}
default:
- LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}",
- static_cast<u32>(num_coordinates));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled coordinates number {}",
+ static_cast<u32>(num_coordinates));
// Fallback to interpreting as a 2D texture for now
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
@@ -2694,9 +2611,8 @@ private:
}
default: {
texture = "texture(" + sampler + ", coords)";
- LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}",
- static_cast<u32>(instr.tex.GetTextureProcessMode()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled texture process mode {}",
+ static_cast<u32>(instr.tex.GetTextureProcessMode()));
}
}
if (!depth_compare) {
@@ -2721,8 +2637,8 @@ private:
Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
bool is_array{instr.texs.IsArrayTexture()};
- ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
- "NODEP is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
+ "NODEP is not implemented");
const bool depth_compare =
instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
@@ -2761,9 +2677,8 @@ private:
break;
}
default:
- LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}",
- static_cast<u32>(num_coordinates));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled coordinates number {}",
+ static_cast<u32>(num_coordinates));
// Fallback to interpreting as a 2D texture for now
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
@@ -2795,9 +2710,8 @@ private:
}
default: {
texture = "texture(" + sampler + ", coords)";
- LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}",
- static_cast<u32>(instr.texs.GetTextureProcessMode()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled texture process mode {}",
+ static_cast<u32>(instr.texs.GetTextureProcessMode()));
}
}
if (!depth_compare) {
@@ -2815,12 +2729,12 @@ private:
ASSERT(texture_type == Tegra::Shader::TextureType::Texture2D);
ASSERT(is_array == false);
- ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
- "NODEP is not implemented");
- ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
- "AOFFI is not implemented");
- ASSERT_MSG(!instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ),
- "MZ is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
+ "NODEP is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
+ "AOFFI is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(Tegra::Shader::TextureMiscMode::MZ),
+ "MZ is not implemented");
u32 op_c_offset = 0;
@@ -2831,21 +2745,16 @@ private:
break;
}
case Tegra::Shader::TextureType::Texture2D: {
- if (is_array) {
- LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture");
- UNREACHABLE();
- } else {
- const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
- const std::string y = regs.GetRegisterAsInteger(instr.gpr20);
- coord = "ivec2 coords = ivec2(" + x + ", " + y + ");";
- op_c_offset = 1;
- }
+ UNIMPLEMENTED_IF_MSG(is_array, "Unhandled 2d array texture");
+
+ const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
+ const std::string y = regs.GetRegisterAsInteger(instr.gpr20);
+ coord = "ivec2 coords = ivec2(" + x + ", " + y + ");";
+ op_c_offset = 1;
break;
}
default:
- LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
- static_cast<u32>(texture_type));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<u32>(texture_type));
}
const std::string sampler =
GetSampler(instr.sampler, texture_type, is_array, false);
@@ -2863,9 +2772,8 @@ private:
}
default: {
texture = "texelFetch(" + sampler + ", coords, 0)";
- LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}",
- static_cast<u32>(instr.tlds.GetTextureProcessMode()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled texture process mode {}",
+ static_cast<u32>(instr.tlds.GetTextureProcessMode()));
}
}
WriteTexsInstruction(instr, coord, texture);
@@ -2876,14 +2784,14 @@ private:
ASSERT(instr.tld4.array == 0);
std::string coord;
- ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
- "NODEP is not implemented");
- ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
- "AOFFI is not implemented");
- ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
- "NDV is not implemented");
- ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP),
- "PTP is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
+ "NODEP is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
+ "AOFFI is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
+ "NDV is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP),
+ "PTP is not implemented");
const bool depth_compare =
instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
auto texture_type = instr.tld4.texture_type.Value();
@@ -2906,9 +2814,8 @@ private:
break;
}
default:
- LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}",
- static_cast<u32>(num_coordinates));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled coordinates number {}",
+ static_cast<u32>(num_coordinates));
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
coord = "vec2 coords = vec2(" + x + ", " + y + ");";
@@ -2942,10 +2849,12 @@ private:
break;
}
case OpCode::Id::TLD4S: {
- ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
- "NODEP is not implemented");
- ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
- "AOFFI is not implemented");
+ UNIMPLEMENTED_IF_MSG(
+ instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
+ "NODEP is not implemented");
+ UNIMPLEMENTED_IF_MSG(
+ instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
+ "AOFFI is not implemented");
const bool depth_compare =
instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
@@ -2973,8 +2882,8 @@ private:
break;
}
case OpCode::Id::TXQ: {
- ASSERT_MSG(!instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
- "NODEP is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
+ "NODEP is not implemented");
// TODO: the new commits on the texture refactor, change the way samplers work.
// Sadly, not all texture instructions specify the type of texture their sampler
@@ -2988,18 +2897,17 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled texture query type: {}",
- static_cast<u32>(instr.txq.query_type.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled texture query type: {}",
+ static_cast<u32>(instr.txq.query_type.Value()));
}
}
break;
}
case OpCode::Id::TMML: {
- ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
- "NODEP is not implemented");
- ASSERT_MSG(!instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
- "NDV is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
+ "NODEP is not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
+ "NDV is not implemented");
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
const bool is_array = instr.tmml.array != 0;
@@ -3021,9 +2929,7 @@ private:
break;
}
default:
- LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
- static_cast<u32>(texture_type));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<u32>(texture_type));
// Fallback to interpreting as a 2D texture for now
const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
@@ -3046,8 +2952,7 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled memory instruction: {}", opcode->get().GetName());
}
}
break;
@@ -3133,7 +3038,7 @@ private:
break;
}
case OpCode::Type::HalfSetPredicate: {
- ASSERT_MSG(instr.hsetp2.ftz == 0, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.hsetp2.ftz != 0);
const std::string op_a =
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hsetp2.type_a,
@@ -3178,6 +3083,8 @@ private:
break;
}
case OpCode::Type::PredicateSetRegister: {
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "PSET Generates an unhandled Control Code");
+
const std::string op_a =
GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0);
const std::string op_b =
@@ -3198,12 +3105,6 @@ private:
const std::string value = '(' + result + ") ? 1.0 : 0.0";
regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1);
}
-
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "PSET Generates an unhandled Control Code");
- UNREACHABLE();
- }
-
break;
}
case OpCode::Type::PredicateSetPredicate: {
@@ -3253,9 +3154,7 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}",
- opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled predicate instruction: {}", opcode->get().GetName());
}
}
break;
@@ -3335,7 +3234,7 @@ private:
break;
}
case OpCode::Type::HalfSet: {
- ASSERT_MSG(instr.hset2.ftz == 0, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.hset2.ftz != 0);
const std::string op_a =
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hset2.type_a,
@@ -3379,15 +3278,16 @@ private:
break;
}
case OpCode::Type::Xmad: {
- ASSERT_MSG(!instr.xmad.sign_a, "Unimplemented");
- ASSERT_MSG(!instr.xmad.sign_b, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.xmad.sign_a);
+ UNIMPLEMENTED_IF(instr.xmad.sign_b);
+ UNIMPLEMENTED_IF_MSG(instr.generates_cc, "XMAD Generates an unhandled Control Code");
std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)};
std::string op_b;
std::string op_c;
// TODO(bunnei): Needs to be fixed once op_a or op_b is signed
- ASSERT_MSG(instr.xmad.sign_a == instr.xmad.sign_b, "Unimplemented");
+ UNIMPLEMENTED_IF(instr.xmad.sign_a != instr.xmad.sign_b);
const bool is_signed{instr.xmad.sign_a == 1};
bool is_merge{};
@@ -3420,8 +3320,7 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->get().GetName());
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled XMAD instruction: {}", opcode->get().GetName());
}
}
@@ -3457,9 +3356,8 @@ private:
op_c = "((" + op_c + ") + (" + src2 + "<< 16))";
break;
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled XMAD mode: {}",
- static_cast<u32>(instr.xmad.mode.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled XMAD mode: {}",
+ static_cast<u32>(instr.xmad.mode.Value()));
}
}
@@ -3469,25 +3367,19 @@ private:
}
regs.SetRegisterToInteger(instr.gpr0, is_signed, 0, sum, 1, 1);
- if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "XMAD Generates an unhandled Control Code");
- UNREACHABLE();
- }
break;
}
default: {
switch (opcode->get().GetId()) {
case OpCode::Id::EXIT: {
+ const Tegra::Shader::ControlCode cc = instr.flow_control_code;
+ UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T,
+ "EXIT Control Code used: {}", static_cast<u32>(cc));
+
if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
EmitFragmentOutputsWrite();
}
- const Tegra::Shader::ControlCode cc = instr.flow_control_code;
- if (cc != Tegra::Shader::ControlCode::T) {
- LOG_CRITICAL(HW_GPU, "EXIT Control Code used: {}", static_cast<u32>(cc));
- UNREACHABLE();
- }
-
switch (instr.flow.cond) {
case Tegra::Shader::FlowCondition::Always:
shader.AddLine("return true;");
@@ -3502,26 +3394,24 @@ private:
case Tegra::Shader::FlowCondition::Fcsm_Tr:
// TODO(bunnei): What is this used for? If we assume this conditon is not
// satisifed, dual vertex shaders in Farming Simulator make more sense
- LOG_CRITICAL(HW_GPU, "Skipping unknown FlowCondition::Fcsm_Tr");
+ UNIMPLEMENTED_MSG("Skipping unknown FlowCondition::Fcsm_Tr");
break;
default:
- LOG_CRITICAL(HW_GPU, "Unhandled flow condition: {}",
- static_cast<u32>(instr.flow.cond.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled flow condition: {}",
+ static_cast<u32>(instr.flow.cond.Value()));
}
break;
}
case OpCode::Id::KIL: {
- ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
+ UNIMPLEMENTED_IF(instr.flow.cond != Tegra::Shader::FlowCondition::Always);
+
+ const Tegra::Shader::ControlCode cc = instr.flow_control_code;
+ UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T,
+ "KIL Control Code used: {}", static_cast<u32>(cc));
// Enclose "discard" in a conditional, so that GLSL compilation does not complain
// about unexecuted instructions that may follow this.
- const Tegra::Shader::ControlCode cc = instr.flow_control_code;
- if (cc != Tegra::Shader::ControlCode::T) {
- LOG_CRITICAL(HW_GPU, "KIL Control Code used: {}", static_cast<u32>(cc));
- UNREACHABLE();
- }
shader.AddLine("if (true) {");
++shader.scope;
shader.AddLine("discard;");
@@ -3531,7 +3421,8 @@ private:
break;
}
case OpCode::Id::OUT_R: {
- ASSERT(instr.gpr20.Value() == Register::ZeroIndex);
+ UNIMPLEMENTED_IF_MSG(instr.gpr20.Value() != Register::ZeroIndex,
+ "Stream buffer is not supported");
ASSERT_MSG(stage == Maxwell3D::Regs::ShaderStage::Geometry,
"OUT is expected to be used in a geometry shader.");
@@ -3558,18 +3449,17 @@ private:
break;
}
default: {
- LOG_CRITICAL(HW_GPU, "Unhandled system move: {}",
- static_cast<u32>(instr.sys20.Value()));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("Unhandled system move: {}",
+ static_cast<u32>(instr.sys20.Value()));
}
}
break;
}
case OpCode::Id::ISBERD: {
- ASSERT(instr.isberd.o == 0);
- ASSERT(instr.isberd.skew == 0);
- ASSERT(instr.isberd.shift == Tegra::Shader::IsberdShift::None);
- ASSERT(instr.isberd.mode == Tegra::Shader::IsberdMode::None);
+ UNIMPLEMENTED_IF(instr.isberd.o != 0);
+ UNIMPLEMENTED_IF(instr.isberd.skew != 0);
+ UNIMPLEMENTED_IF(instr.isberd.shift != Tegra::Shader::IsberdShift::None);
+ UNIMPLEMENTED_IF(instr.isberd.mode != Tegra::Shader::IsberdMode::None);
ASSERT_MSG(stage == Maxwell3D::Regs::ShaderStage::Geometry,
"ISBERD is expected to be used in a geometry shader.");
LOG_WARNING(HW_GPU, "ISBERD instruction is incomplete");
@@ -3577,13 +3467,13 @@ private:
break;
}
case OpCode::Id::BRA: {
- ASSERT_MSG(instr.bra.constant_buffer == 0,
- "BRA with constant buffers are not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
+ "BRA with constant buffers are not implemented");
+
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
- if (cc != Tegra::Shader::ControlCode::T) {
- LOG_CRITICAL(HW_GPU, "BRA Control Code used: {}", static_cast<u32>(cc));
- UNREACHABLE();
- }
+ UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T,
+ "BRA Control Code used: {}", static_cast<u32>(cc));
+
const u32 target = offset + instr.bra.GetBranchTarget();
shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }");
break;
@@ -3606,7 +3496,8 @@ private:
// The SSY opcode tells the GPU where to re-converge divergent execution paths, it
// sets the target of the jump that the SYNC instruction will make. The SSY opcode
// has a similar structure to the BRA opcode.
- ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer flow is not supported");
+ UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
+ "Constant buffer flow is not supported");
const u32 target = offset + instr.bra.GetBranchTarget();
EmitPushToFlowStack(target);
@@ -3616,19 +3507,19 @@ private:
// PBK pushes to a stack the address where BRK will jump to. This shares stack with
// SSY but using SYNC on a PBK address will kill the shader execution. We don't
// emulate this because it's very unlikely a driver will emit such invalid shader.
- ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer PBK is not supported");
+ UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
+ "Constant buffer PBK is not supported");
const u32 target = offset + instr.bra.GetBranchTarget();
EmitPushToFlowStack(target);
break;
}
case OpCode::Id::SYNC: {
- // The SYNC opcode jumps to the address previously set by the SSY opcode
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
- if (cc != Tegra::Shader::ControlCode::T) {
- LOG_CRITICAL(HW_GPU, "SYNC Control Code used: {}", static_cast<u32>(cc));
- UNREACHABLE();
- }
+ UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ControlCode::T,
+ "SYNC Control Code used: {}", static_cast<u32>(cc));
+
+ // The SYNC opcode jumps to the address previously set by the SSY opcode
EmitPopFromFlowStack();
break;
}
@@ -3636,8 +3527,7 @@ private:
// The BRK opcode jumps to the address previously set by the PBK opcode
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
if (cc != Tegra::Shader::ControlCode::T) {
- LOG_CRITICAL(HW_GPU, "BRK Control Code used: {}", static_cast<u32>(cc));
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("BRK Control Code used: {}", static_cast<u32>(cc));
}
EmitPopFromFlowStack();
break;
@@ -3669,8 +3559,7 @@ private:
instr.vmad.saturate == 1, 0, Register::Size::Word,
instr.vmad.cc);
if (instr.generates_cc) {
- LOG_CRITICAL(HW_GPU, "VMAD Generates an unhandled Control Code");
- UNREACHABLE();
+ UNIMPLEMENTED_MSG("VMAD Generates an unhandled Control Code");
}
break;
@@ -3699,10 +3588,7 @@ private:
}
break;
}
- default: {
- LOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->get().GetName());
- UNREACHABLE();
- }
+ default: { UNIMPLEMENTED_MSG("Unhandled instruction: {}", opcode->get().GetName()); }
}
break;