summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/frontend/maxwell/location.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/frontend/maxwell/location.h106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/location.h b/src/shader_recompiler/frontend/maxwell/location.h
new file mode 100644
index 000000000..66b51a19e
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/location.h
@@ -0,0 +1,106 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <compare>
+#include <iterator>
+
+#include <fmt/format.h>
+
+#include "common/common_types.h"
+#include "shader_recompiler/exception.h"
+
+namespace Shader::Maxwell {
+
+class Location {
+ static constexpr u32 VIRTUAL_OFFSET{std::numeric_limits<u32>::max()};
+
+public:
+ constexpr Location() = default;
+
+ constexpr Location(u32 initial_offset) : offset{initial_offset} {
+ if (initial_offset % 8 != 0) {
+ throw InvalidArgument("initial_offset={} is not a multiple of 8", initial_offset);
+ }
+ Align();
+ }
+
+ [[nodiscard]] constexpr u32 Offset() const noexcept {
+ return offset;
+ }
+
+ [[nodiscard]] constexpr bool IsVirtual() const {
+ return offset == VIRTUAL_OFFSET;
+ }
+
+ constexpr auto operator<=>(const Location&) const noexcept = default;
+
+ constexpr Location operator++() noexcept {
+ const Location copy{*this};
+ Step();
+ return copy;
+ }
+
+ constexpr Location operator++(int) noexcept {
+ Step();
+ return *this;
+ }
+
+ constexpr Location operator--() noexcept {
+ const Location copy{*this};
+ Back();
+ return copy;
+ }
+
+ constexpr Location operator--(int) noexcept {
+ Back();
+ return *this;
+ }
+
+ constexpr Location operator+(int number) const {
+ Location new_pc{*this};
+ while (number > 0) {
+ --number;
+ ++new_pc;
+ }
+ while (number < 0) {
+ ++number;
+ --new_pc;
+ }
+ return new_pc;
+ }
+
+ constexpr Location operator-(int number) const {
+ return operator+(-number);
+ }
+
+private:
+ constexpr void Align() {
+ offset += offset % 32 == 0 ? 8 : 0;
+ }
+
+ constexpr void Step() {
+ offset += 8 + (offset % 32 == 24 ? 8 : 0);
+ }
+
+ constexpr void Back() {
+ offset -= 8 + (offset % 32 == 8 ? 8 : 0);
+ }
+
+ u32 offset{VIRTUAL_OFFSET};
+};
+
+} // namespace Shader::Maxwell
+
+template <>
+struct fmt::formatter<Shader::Maxwell::Location> {
+ constexpr auto parse(format_parse_context& ctx) {
+ return ctx.begin();
+ }
+ template <typename FormatContext>
+ auto format(const Shader::Maxwell::Location& location, FormatContext& ctx) {
+ return fmt::format_to(ctx.out(), "{:04x}", location.Offset());
+ }
+};