summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/file_util.cpp38
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp67
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h30
-rw-r--r--src/core/arm/exclusive_monitor.cpp7
-rw-r--r--src/core/arm/exclusive_monitor.h23
-rw-r--r--src/core/core.cpp3
-rw-r--r--src/core/core.h12
-rw-r--r--src/core/core_cpu.cpp19
-rw-r--r--src/core/core_cpu.h10
-rw-r--r--src/video_core/engines/shader_bytecode.h11
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp114
12 files changed, 217 insertions, 119 deletions
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 13fc31bfc..1bc291cf9 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <array>
+#include <memory>
#include <sstream>
#include <unordered_map>
#include "common/assert.h"
@@ -275,14 +277,10 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
GetLastErrorMsg());
return false;
#else
-
-// buffer size
-#define BSIZE 1024
-
- char buffer[BSIZE];
+ using CFilePointer = std::unique_ptr<FILE, decltype(&std::fclose)>;
// Open input file
- FILE* input = fopen(srcFilename.c_str(), "rb");
+ CFilePointer input{fopen(srcFilename.c_str(), "rb"), std::fclose};
if (!input) {
LOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename,
destFilename, GetLastErrorMsg());
@@ -290,44 +288,36 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
}
// open output file
- FILE* output = fopen(destFilename.c_str(), "wb");
+ CFilePointer output{fopen(destFilename.c_str(), "wb"), std::fclose};
if (!output) {
- fclose(input);
LOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename,
destFilename, GetLastErrorMsg());
return false;
}
// copy loop
- while (!feof(input)) {
+ std::array<char, 1024> buffer;
+ while (!feof(input.get())) {
// read input
- size_t rnum = fread(buffer, sizeof(char), BSIZE, input);
- if (rnum != BSIZE) {
- if (ferror(input) != 0) {
+ size_t rnum = fread(buffer.data(), sizeof(char), buffer.size(), input.get());
+ if (rnum != buffer.size()) {
+ if (ferror(input.get()) != 0) {
LOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}",
srcFilename, destFilename, GetLastErrorMsg());
- goto bail;
+ return false;
}
}
// write output
- size_t wnum = fwrite(buffer, sizeof(char), rnum, output);
+ size_t wnum = fwrite(buffer.data(), sizeof(char), rnum, output.get());
if (wnum != rnum) {
LOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename,
destFilename, GetLastErrorMsg());
- goto bail;
+ return false;
}
}
- // close files
- fclose(input);
- fclose(output);
+
return true;
-bail:
- if (input)
- fclose(input);
- if (output)
- fclose(output);
- return false;
#endif
}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0a5d58eea..27a5de7fd 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,5 +1,7 @@
add_library(core STATIC
arm/arm_interface.h
+ arm/exclusive_monitor.cpp
+ arm/exclusive_monitor.h
arm/unicorn/arm_unicorn.cpp
arm/unicorn/arm_unicorn.h
core.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 5d7efc9b6..83c09db2b 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -102,18 +102,28 @@ public:
u64 tpidr_el0 = 0;
};
-std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) {
+std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() {
const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
Dynarmic::A64::UserConfig config;
+
+ // Callbacks
config.callbacks = cb.get();
+
+ // Memory
+ config.page_table = reinterpret_cast<void**>(page_table);
+ config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
+ config.silently_mirror_page_table = false;
+
+ // Multi-process state
+ config.processor_id = core_index;
+ config.global_monitor = &exclusive_monitor->monitor;
+
+ // System registers
config.tpidrro_el0 = &cb->tpidrro_el0;
config.tpidr_el0 = &cb->tpidr_el0;
config.dczid_el0 = 4;
config.ctr_el0 = 0x8444c004;
- config.page_table = reinterpret_cast<void**>(page_table);
- config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
- config.silently_mirror_page_table = false;
return std::make_unique<Dynarmic::A64::Jit>(config);
}
@@ -128,8 +138,11 @@ void ARM_Dynarmic::Step() {
cb->InterpreterFallback(jit->GetPC(), 1);
}
-ARM_Dynarmic::ARM_Dynarmic()
- : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) {
+ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index)
+ : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)),
+ jit(MakeJit()), exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(
+ exclusive_monitor)},
+ core_index{core_index} {
ARM_Interface::ThreadContext ctx;
inner_unicorn.SaveContext(ctx);
LoadContext(ctx);
@@ -237,6 +250,46 @@ void ARM_Dynarmic::ClearExclusiveState() {
}
void ARM_Dynarmic::PageTableChanged() {
- jit = MakeJit(cb);
+ jit = MakeJit();
current_page_table = Memory::GetCurrentPageTable();
}
+
+DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(size_t core_count) : monitor(core_count) {}
+DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
+
+void DynarmicExclusiveMonitor::SetExclusive(size_t core_index, u64 addr) {
+ // Size doesn't actually matter.
+ monitor.Mark(core_index, addr, 16);
+}
+
+void DynarmicExclusiveMonitor::ClearExclusive() {
+ monitor.Clear();
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 1,
+ [&] { Memory::Write8(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 2,
+ [&] { Memory::Write16(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 4,
+ [&] { Memory::Write32(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 8,
+ [&] { Memory::Write64(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
+ Memory::Write64(vaddr, value[0]);
+ Memory::Write64(vaddr, value[1]);
+ });
+}
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index a9891ac4f..0fa8b417c 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -6,15 +6,18 @@
#include <memory>
#include <dynarmic/A64/a64.h>
+#include <dynarmic/A64/exclusive_monitor.h>
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
+#include "core/arm/exclusive_monitor.h"
#include "core/arm/unicorn/arm_unicorn.h"
class ARM_Dynarmic_Callbacks;
+class DynarmicExclusiveMonitor;
class ARM_Dynarmic final : public ARM_Interface {
public:
- ARM_Dynarmic();
+ ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index);
~ARM_Dynarmic();
void MapBackingMemory(VAddr address, size_t size, u8* memory,
@@ -47,10 +50,35 @@ public:
void PageTableChanged() override;
private:
+ std::unique_ptr<Dynarmic::A64::Jit> MakeJit();
+
friend class ARM_Dynarmic_Callbacks;
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
std::unique_ptr<Dynarmic::A64::Jit> jit;
ARM_Unicorn inner_unicorn;
+ size_t core_index;
+ std::shared_ptr<DynarmicExclusiveMonitor> exclusive_monitor;
+
Memory::PageTable* current_page_table = nullptr;
};
+
+class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
+public:
+ explicit DynarmicExclusiveMonitor(size_t core_count);
+ ~DynarmicExclusiveMonitor();
+
+ void SetExclusive(size_t core_index, u64 addr) override;
+ void ClearExclusive() override;
+
+ bool ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) override;
+ bool ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) override;
+ bool ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) override;
+ bool ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) override;
+ bool ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) override;
+
+private:
+ friend class ARM_Dynarmic;
+ Dynarmic::A64::ExclusiveMonitor monitor;
+};
diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp
new file mode 100644
index 000000000..cb8c81d80
--- /dev/null
+++ b/src/core/arm/exclusive_monitor.cpp
@@ -0,0 +1,7 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/arm/exclusive_monitor.h"
+
+ExclusiveMonitor::~ExclusiveMonitor() = default;
diff --git a/src/core/arm/exclusive_monitor.h b/src/core/arm/exclusive_monitor.h
new file mode 100644
index 000000000..acfcdb94c
--- /dev/null
+++ b/src/core/arm/exclusive_monitor.h
@@ -0,0 +1,23 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include "common/common_types.h"
+
+class ExclusiveMonitor {
+public:
+ virtual ~ExclusiveMonitor();
+
+ virtual void SetExclusive(size_t core_index, u64 addr) = 0;
+ virtual void ClearExclusive() = 0;
+
+ virtual bool ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) = 0;
+ virtual bool ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) = 0;
+ virtual bool ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) = 0;
+ virtual bool ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) = 0;
+ virtual bool ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) = 0;
+};
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 9bd9f4bd9..b7f4b4532 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -171,8 +171,9 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
current_process = Kernel::Process::Create("main");
cpu_barrier = std::make_shared<CpuBarrier>();
+ cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size());
for (size_t index = 0; index < cpu_cores.size(); ++index) {
- cpu_cores[index] = std::make_shared<Cpu>(cpu_barrier, index);
+ cpu_cores[index] = std::make_shared<Cpu>(cpu_exclusive_monitor, cpu_barrier, index);
}
gpu_core = std::make_unique<Tegra::GPU>();
diff --git a/src/core/core.h b/src/core/core.h
index c6f69f001..c123fe401 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -9,6 +9,7 @@
#include <string>
#include <thread>
#include "common/common_types.h"
+#include "core/arm/exclusive_monitor.h"
#include "core/core_cpu.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/scheduler.h"
@@ -114,6 +115,11 @@ public:
return CurrentCpuCore().ArmInterface();
}
+ /// Gets the index of the currently running CPU core
+ size_t CurrentCoreIndex() {
+ return CurrentCpuCore().CoreIndex();
+ }
+
/// Gets an ARM interface to the CPU core with the specified index
ARM_Interface& ArmInterface(size_t core_index);
@@ -130,6 +136,11 @@ public:
return *CurrentCpuCore().Scheduler();
}
+ /// Gets the exclusive monitor
+ ExclusiveMonitor& Monitor() {
+ return *cpu_exclusive_monitor;
+ }
+
/// Gets the scheduler for the CPU core with the specified index
const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index);
@@ -186,6 +197,7 @@ private:
std::unique_ptr<Tegra::GPU> gpu_core;
std::shared_ptr<Tegra::DebugContext> debug_context;
Kernel::SharedPtr<Kernel::Process> current_process;
+ std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor;
std::shared_ptr<CpuBarrier> cpu_barrier;
std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores;
std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads;
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index f22d6a9d0..54e15a701 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -48,14 +48,15 @@ bool CpuBarrier::Rendezvous() {
return false;
}
-Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
+Cpu::Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
+ std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
: cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} {
if (Settings::values.use_cpu_jit) {
#ifdef ARCHITECTURE_x86_64
- arm_interface = std::make_shared<ARM_Dynarmic>();
+ arm_interface = std::make_shared<ARM_Dynarmic>(exclusive_monitor, core_index);
#else
- cpu_core = std::make_shared<ARM_Unicorn>();
+ arm_interface = std::make_shared<ARM_Unicorn>();
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
#endif
} else {
@@ -65,6 +66,18 @@ Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
}
+std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(size_t num_cores) {
+ if (Settings::values.use_cpu_jit) {
+#ifdef ARCHITECTURE_x86_64
+ return std::make_shared<DynarmicExclusiveMonitor>(num_cores);
+#else
+ return nullptr; // TODO(merry): Passthrough exclusive monitor
+#endif
+ } else {
+ return nullptr; // TODO(merry): Passthrough exclusive monitor
+ }
+}
+
void Cpu::RunLoop(bool tight_loop) {
// Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
if (!cpu_barrier->Rendezvous()) {
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index 243f0b5e7..976952903 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -10,6 +10,7 @@
#include <mutex>
#include <string>
#include "common/common_types.h"
+#include "core/arm/exclusive_monitor.h"
class ARM_Interface;
@@ -40,7 +41,8 @@ private:
class Cpu {
public:
- Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index);
+ Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
+ std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index);
void RunLoop(bool tight_loop = true);
@@ -64,6 +66,12 @@ public:
return core_index == 0;
}
+ size_t CoreIndex() const {
+ return core_index;
+ }
+
+ static std::shared_ptr<ExclusiveMonitor> MakeExclusiveMonitor(size_t num_cores);
+
private:
void Reschedule();
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 939a71022..f495b623b 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -290,6 +290,11 @@ union Instruction {
union {
BitField<39, 3, u64> pred;
+ BitField<42, 1, u64> neg_pred;
+ } sel;
+
+ union {
+ BitField<39, 3, u64> pred;
BitField<42, 1, u64> negate_pred;
BitField<43, 2, IMinMaxExchange> exchange;
BitField<48, 1, u64> is_signed;
@@ -513,6 +518,9 @@ public:
ISCADD_C, // Scale and Add
ISCADD_R,
ISCADD_IMM,
+ SEL_C,
+ SEL_R,
+ SEL_IMM,
MUFU, // Multi-Function Operator
RRO_C, // Range Reduction Operator
RRO_R,
@@ -713,6 +721,9 @@ private:
INST("0100110000011---", Id::ISCADD_C, Type::ArithmeticInteger, "ISCADD_C"),
INST("0101110000011---", Id::ISCADD_R, Type::ArithmeticInteger, "ISCADD_R"),
INST("0011100-00011---", Id::ISCADD_IMM, Type::ArithmeticInteger, "ISCADD_IMM"),
+ INST("0100110010100---", Id::SEL_C, Type::ArithmeticInteger, "SEL_C"),
+ INST("0101110010100---", Id::SEL_R, Type::ArithmeticInteger, "SEL_R"),
+ INST("0011100010100---", Id::SEL_IMM, Type::ArithmeticInteger, "SEL_IMM"),
INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index b48d30466..ba827181b 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -78,14 +78,18 @@ private:
/// Adds and analyzes a new subroutine if it is not added yet.
const Subroutine& AddSubroutine(u32 begin, u32 end, const std::string& suffix) {
- auto iter = subroutines.find(Subroutine{begin, end, suffix});
- if (iter != subroutines.end())
+ Subroutine subroutine{begin, end, suffix, ExitMethod::Undetermined, {}};
+
+ const auto iter = subroutines.find(subroutine);
+ if (iter != subroutines.end()) {
return *iter;
+ }
- Subroutine subroutine{begin, end, suffix};
subroutine.exit_method = Scan(begin, end, subroutine.labels);
- if (subroutine.exit_method == ExitMethod::Undetermined)
+ if (subroutine.exit_method == ExitMethod::Undetermined) {
throw DecompileFail("Recursive function detected");
+ }
+
return *subroutines.insert(std::move(subroutine)).first;
}
@@ -191,48 +195,21 @@ public:
UnsignedInteger,
};
- GLSLRegister(size_t index, ShaderWriter& shader, const std::string& suffix)
- : index{index}, shader{shader}, suffix{suffix} {}
+ GLSLRegister(size_t index, const std::string& suffix) : index{index}, suffix{suffix} {}
/// Gets the GLSL type string for a register
- static std::string GetTypeString(Type type) {
- switch (type) {
- case Type::Float:
- return "float";
- case Type::Integer:
- return "int";
- case Type::UnsignedInteger:
- return "uint";
- }
-
- UNREACHABLE();
- return {};
+ static std::string GetTypeString() {
+ return "float";
}
/// Gets the GLSL register prefix string, used for declarations and referencing
- static std::string GetPrefixString(Type type) {
- return "reg_" + GetTypeString(type) + '_';
+ static std::string GetPrefixString() {
+ return "reg_";
}
/// Returns a GLSL string representing the current state of the register
- std::string GetActiveString() {
- declr_type.insert(active_type);
- return GetPrefixString(active_type) + std::to_string(index) + '_' + suffix;
- }
-
- /// Returns true if the active type is a float
- bool IsFloat() const {
- return active_type == Type::Float;
- }
-
- /// Returns true if the active type is an integer
- bool IsInteger() const {
- return active_type == Type::Integer;
- }
-
- /// Returns the current active type of the register
- Type GetActiveType() const {
- return active_type;
+ std::string GetString() const {
+ return GetPrefixString() + std::to_string(index) + '_' + suffix;
}
/// Returns the index of the register
@@ -240,18 +217,8 @@ public:
return index;
}
- /// Returns a set of the declared types of the register
- const std::set<Type>& DeclaredTypes() const {
- return declr_type;
- }
-
private:
const size_t index;
- const std::string float_str;
- const std::string integer_str;
- ShaderWriter& shader;
- Type active_type{Type::Float};
- std::set<Type> declr_type;
const std::string& suffix;
};
@@ -297,7 +264,6 @@ public:
* @returns GLSL string corresponding to the register as a float.
*/
std::string GetRegisterAsFloat(const Register& reg, unsigned elem = 0) {
- ASSERT(regs[reg].IsFloat());
return GetRegister(reg, elem);
}
@@ -311,12 +277,8 @@ public:
*/
std::string GetRegisterAsInteger(const Register& reg, unsigned elem = 0, bool is_signed = true,
Register::Size size = Register::Size::Word) {
- const std::string func = GetGLSLConversionFunc(
- GLSLRegister::Type::Float,
- is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger);
-
- std::string value = func + '(' + GetRegister(reg, elem) + ')';
-
+ const std::string func{is_signed ? "floatBitsToInt" : "floatBitsToUint"};
+ const std::string value{func + '(' + GetRegister(reg, elem) + ')'};
return ConvertIntegerSize(value, size);
}
@@ -355,9 +317,7 @@ public:
u64 dest_elem = 0, Register::Size size = Register::Size::Word) {
ASSERT_MSG(!is_saturated, "Unimplemented");
- const std::string func = GetGLSLConversionFunc(
- is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger,
- GLSLRegister::Type::Float);
+ const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"};
SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')',
dest_num_components, value_num_components, dest_elem);
@@ -373,14 +333,7 @@ public:
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) {
std::string dest = GetRegisterAsFloat(reg);
std::string src = GetInputAttribute(attribute) + GetSwizzle(elem);
-
- if (regs[reg].IsFloat()) {
- shader.AddLine(dest + " = " + src + ';');
- } else if (regs[reg].IsInteger()) {
- shader.AddLine(dest + " = floatBitsToInt(" + src + ");");
- } else {
- UNREACHABLE();
- }
+ shader.AddLine(dest + " = " + src + ';');
}
/**
@@ -393,7 +346,6 @@ public:
void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) {
std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem);
std::string src = GetRegisterAsFloat(reg);
- ASSERT_MSG(regs[reg].IsFloat(), "Output attributes must be set to a float");
shader.AddLine(dest + " = " + src + ';');
}
@@ -434,11 +386,8 @@ public:
/// Add declarations for registers
void GenerateDeclarations(const std::string& suffix) {
for (const auto& reg : regs) {
- for (const auto& type : reg.DeclaredTypes()) {
- declarations.AddLine(GLSLRegister::GetTypeString(type) + ' ' +
- reg.GetPrefixString(type) + std::to_string(reg.GetIndex()) +
- '_' + suffix + " = 0;");
- }
+ declarations.AddLine(GLSLRegister::GetTypeString() + ' ' + reg.GetPrefixString() +
+ std::to_string(reg.GetIndex()) + '_' + suffix + " = 0;");
}
declarations.AddNewLine();
@@ -516,21 +465,13 @@ public:
}
private:
- /// Build GLSL conversion function, e.g. floatBitsToInt, intBitsToFloat, etc.
- std::string GetGLSLConversionFunc(GLSLRegister::Type src, GLSLRegister::Type dest) const {
- const std::string src_type = GLSLRegister::GetTypeString(src);
- std::string dest_type = GLSLRegister::GetTypeString(dest);
- dest_type[0] = toupper(dest_type[0]);
- return src_type + "BitsTo" + dest_type;
- }
-
/// Generates code representing a temporary (GPR) register.
std::string GetRegister(const Register& reg, unsigned elem) {
if (reg == Register::ZeroIndex) {
return "0";
}
- return regs[reg.GetSwizzledIndex(elem)].GetActiveString();
+ return regs[reg.GetSwizzledIndex(elem)].GetString();
}
/**
@@ -560,7 +501,7 @@ private:
/// Build the GLSL register list.
void BuildRegisterList() {
for (size_t index = 0; index < Register::NumRegisters; ++index) {
- regs.emplace_back(index, shader, suffix);
+ regs.emplace_back(index, suffix);
}
}
@@ -1139,6 +1080,15 @@ private:
"((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
break;
}
+ case OpCode::Id::SEL_C:
+ case OpCode::Id::SEL_R:
+ case OpCode::Id::SEL_IMM: {
+ std::string condition =
+ GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0);
+ regs.SetRegisterToInteger(instr.gpr0, true, 0,
+ '(' + condition + ") ? " + op_a + " : " + op_b, 1, 1);
+ break;
+ }
case OpCode::Id::LOP_C:
case OpCode::Id::LOP_R:
case OpCode::Id::LOP_IMM: {