diff options
| -rw-r--r-- | src/common/settings.h | 1 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.cpp | 8 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 21 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 21 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_cpu_debug.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_cpu_debug.ui | 13 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 1 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 4 |
9 files changed, 69 insertions, 6 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index c0620066c..29b730cff 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -400,6 +400,7 @@ struct Values { | |||
| 400 | Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; | 400 | Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; |
| 401 | Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; | 401 | Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; |
| 402 | Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; | 402 | Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; |
| 403 | Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"}; | ||
| 403 | 404 | ||
| 404 | SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; | 405 | SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; |
| 405 | SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; | 406 | SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; |
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 29ba562dc..2df7b0ee8 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp | |||
| @@ -145,11 +145,15 @@ void ARM_Interface::Run() { | |||
| 145 | // Notify the debugger and go to sleep if a breakpoint was hit, | 145 | // Notify the debugger and go to sleep if a breakpoint was hit, |
| 146 | // or if the thread is unable to continue for any reason. | 146 | // or if the thread is unable to continue for any reason. |
| 147 | if (Has(hr, breakpoint) || Has(hr, no_execute)) { | 147 | if (Has(hr, breakpoint) || Has(hr, no_execute)) { |
| 148 | RewindBreakpointInstruction(); | 148 | if (!Has(hr, no_execute)) { |
| 149 | RewindBreakpointInstruction(); | ||
| 150 | } | ||
| 149 | if (system.DebuggerEnabled()) { | 151 | if (system.DebuggerEnabled()) { |
| 150 | system.GetDebugger().NotifyThreadStopped(current_thread); | 152 | system.GetDebugger().NotifyThreadStopped(current_thread); |
| 153 | } else { | ||
| 154 | LogBacktrace(); | ||
| 151 | } | 155 | } |
| 152 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | 156 | current_thread->RequestSuspend(SuspendType::Debug); |
| 153 | break; | 157 | break; |
| 154 | } | 158 | } |
| 155 | 159 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 227e06ea1..947747d36 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -29,7 +29,9 @@ class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | |||
| 29 | public: | 29 | public: |
| 30 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) | 30 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) |
| 31 | : parent{parent_}, | 31 | : parent{parent_}, |
| 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} | 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, |
| 33 | check_memory_access{debugger_enabled || | ||
| 34 | !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} | ||
| 33 | 35 | ||
| 34 | u8 MemoryRead8(u32 vaddr) override { | 36 | u8 MemoryRead8(u32 vaddr) override { |
| 35 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); | 37 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); |
| @@ -154,6 +156,17 @@ public: | |||
| 154 | } | 156 | } |
| 155 | 157 | ||
| 156 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { | 158 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { |
| 159 | if (!check_memory_access) { | ||
| 160 | return true; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (!memory.IsValidVirtualAddressRange(addr, size)) { | ||
| 164 | LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", | ||
| 165 | addr); | ||
| 166 | parent.jit.load()->HaltExecution(ARM_Interface::no_execute); | ||
| 167 | return false; | ||
| 168 | } | ||
| 169 | |||
| 157 | if (!debugger_enabled) { | 170 | if (!debugger_enabled) { |
| 158 | return true; | 171 | return true; |
| 159 | } | 172 | } |
| @@ -181,7 +194,8 @@ public: | |||
| 181 | ARM_Dynarmic_32& parent; | 194 | ARM_Dynarmic_32& parent; |
| 182 | Core::Memory::Memory& memory; | 195 | Core::Memory::Memory& memory; |
| 183 | std::size_t num_interpreted_instructions{}; | 196 | std::size_t num_interpreted_instructions{}; |
| 184 | bool debugger_enabled{}; | 197 | const bool debugger_enabled{}; |
| 198 | const bool check_memory_access{}; | ||
| 185 | static constexpr u64 minimum_run_cycles = 10000U; | 199 | static constexpr u64 minimum_run_cycles = 10000U; |
| 186 | }; | 200 | }; |
| 187 | 201 | ||
| @@ -264,6 +278,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 264 | if (!Settings::values.cpuopt_recompile_exclusives) { | 278 | if (!Settings::values.cpuopt_recompile_exclusives) { |
| 265 | config.recompile_on_exclusive_fastmem_failure = false; | 279 | config.recompile_on_exclusive_fastmem_failure = false; |
| 266 | } | 280 | } |
| 281 | if (!Settings::values.cpuopt_ignore_memory_aborts) { | ||
| 282 | config.check_halt_on_memory_access = true; | ||
| 283 | } | ||
| 267 | } else { | 284 | } else { |
| 268 | // Unsafe optimizations | 285 | // Unsafe optimizations |
| 269 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 286 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index cb53d64ba..3df943df7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -29,7 +29,9 @@ class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | |||
| 29 | public: | 29 | public: |
| 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) | 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) |
| 31 | : parent{parent_}, | 31 | : parent{parent_}, |
| 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} | 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, |
| 33 | check_memory_access{debugger_enabled || | ||
| 34 | !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} | ||
| 33 | 35 | ||
| 34 | u8 MemoryRead8(u64 vaddr) override { | 36 | u8 MemoryRead8(u64 vaddr) override { |
| 35 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); | 37 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); |
| @@ -198,6 +200,17 @@ public: | |||
| 198 | } | 200 | } |
| 199 | 201 | ||
| 200 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { | 202 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { |
| 203 | if (!check_memory_access) { | ||
| 204 | return true; | ||
| 205 | } | ||
| 206 | |||
| 207 | if (!memory.IsValidVirtualAddressRange(addr, size)) { | ||
| 208 | LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", | ||
| 209 | addr); | ||
| 210 | parent.jit.load()->HaltExecution(ARM_Interface::no_execute); | ||
| 211 | return false; | ||
| 212 | } | ||
| 213 | |||
| 201 | if (!debugger_enabled) { | 214 | if (!debugger_enabled) { |
| 202 | return true; | 215 | return true; |
| 203 | } | 216 | } |
| @@ -226,7 +239,8 @@ public: | |||
| 226 | Core::Memory::Memory& memory; | 239 | Core::Memory::Memory& memory; |
| 227 | u64 tpidrro_el0 = 0; | 240 | u64 tpidrro_el0 = 0; |
| 228 | u64 tpidr_el0 = 0; | 241 | u64 tpidr_el0 = 0; |
| 229 | bool debugger_enabled{}; | 242 | const bool debugger_enabled{}; |
| 243 | const bool check_memory_access{}; | ||
| 230 | static constexpr u64 minimum_run_cycles = 10000U; | 244 | static constexpr u64 minimum_run_cycles = 10000U; |
| 231 | }; | 245 | }; |
| 232 | 246 | ||
| @@ -323,6 +337,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 323 | if (!Settings::values.cpuopt_recompile_exclusives) { | 337 | if (!Settings::values.cpuopt_recompile_exclusives) { |
| 324 | config.recompile_on_exclusive_fastmem_failure = false; | 338 | config.recompile_on_exclusive_fastmem_failure = false; |
| 325 | } | 339 | } |
| 340 | if (!Settings::values.cpuopt_ignore_memory_aborts) { | ||
| 341 | config.check_halt_on_memory_access = true; | ||
| 342 | } | ||
| 326 | } else { | 343 | } else { |
| 327 | // Unsafe optimizations | 344 | // Unsafe optimizations |
| 328 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 345 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index c11d1c8b3..722fc708e 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -679,6 +679,7 @@ void Config::ReadCpuValues() { | |||
| 679 | ReadBasicSetting(Settings::values.cpuopt_fastmem); | 679 | ReadBasicSetting(Settings::values.cpuopt_fastmem); |
| 680 | ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives); | 680 | ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives); |
| 681 | ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives); | 681 | ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives); |
| 682 | ReadBasicSetting(Settings::values.cpuopt_ignore_memory_aborts); | ||
| 682 | } | 683 | } |
| 683 | 684 | ||
| 684 | qt_config->endGroup(); | 685 | qt_config->endGroup(); |
| @@ -1291,6 +1292,7 @@ void Config::SaveCpuValues() { | |||
| 1291 | WriteBasicSetting(Settings::values.cpuopt_fastmem); | 1292 | WriteBasicSetting(Settings::values.cpuopt_fastmem); |
| 1292 | WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives); | 1293 | WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives); |
| 1293 | WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives); | 1294 | WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives); |
| 1295 | WriteBasicSetting(Settings::values.cpuopt_ignore_memory_aborts); | ||
| 1294 | } | 1296 | } |
| 1295 | 1297 | ||
| 1296 | qt_config->endGroup(); | 1298 | qt_config->endGroup(); |
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp index 3c302ec16..8cfef0cc1 100644 --- a/src/yuzu/configuration/configure_cpu_debug.cpp +++ b/src/yuzu/configuration/configure_cpu_debug.cpp | |||
| @@ -45,6 +45,9 @@ void ConfigureCpuDebug::SetConfiguration() { | |||
| 45 | ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock); | 45 | ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock); |
| 46 | ui->cpuopt_recompile_exclusives->setChecked( | 46 | ui->cpuopt_recompile_exclusives->setChecked( |
| 47 | Settings::values.cpuopt_recompile_exclusives.GetValue()); | 47 | Settings::values.cpuopt_recompile_exclusives.GetValue()); |
| 48 | ui->cpuopt_ignore_memory_aborts->setEnabled(runtime_lock); | ||
| 49 | ui->cpuopt_ignore_memory_aborts->setChecked( | ||
| 50 | Settings::values.cpuopt_ignore_memory_aborts.GetValue()); | ||
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | void ConfigureCpuDebug::ApplyConfiguration() { | 53 | void ConfigureCpuDebug::ApplyConfiguration() { |
| @@ -59,6 +62,7 @@ void ConfigureCpuDebug::ApplyConfiguration() { | |||
| 59 | Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked(); | 62 | Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked(); |
| 60 | Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked(); | 63 | Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked(); |
| 61 | Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked(); | 64 | Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked(); |
| 65 | Settings::values.cpuopt_ignore_memory_aborts = ui->cpuopt_ignore_memory_aborts->isChecked(); | ||
| 62 | } | 66 | } |
| 63 | 67 | ||
| 64 | void ConfigureCpuDebug::changeEvent(QEvent* event) { | 68 | void ConfigureCpuDebug::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/configuration/configure_cpu_debug.ui b/src/yuzu/configuration/configure_cpu_debug.ui index 2bc268810..3010f7fad 100644 --- a/src/yuzu/configuration/configure_cpu_debug.ui +++ b/src/yuzu/configuration/configure_cpu_debug.ui | |||
| @@ -175,6 +175,19 @@ | |||
| 175 | </property> | 175 | </property> |
| 176 | </widget> | 176 | </widget> |
| 177 | </item> | 177 | </item> |
| 178 | <item> | ||
| 179 | <widget class="QCheckBox" name="cpuopt_ignore_memory_aborts"> | ||
| 180 | <property name="toolTip"> | ||
| 181 | <string> | ||
| 182 | <div style="white-space: nowrap">This optimization speeds up memory accesses by allowing invalid memory accesses to succeed.</div> | ||
| 183 | <div style="white-space: nowrap">Enabling it reduces the overhead of all memory accesses and has no impact on programs that don't access invalid memory.</div> | ||
| 184 | </string> | ||
| 185 | </property> | ||
| 186 | <property name="text"> | ||
| 187 | <string>Enable fallbacks for invalid memory accesses</string> | ||
| 188 | </property> | ||
| 189 | </widget> | ||
| 190 | </item> | ||
| 178 | </layout> | 191 | </layout> |
| 179 | </widget> | 192 | </widget> |
| 180 | </item> | 193 | </item> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 2c78e776c..de9b220da 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -286,6 +286,7 @@ void Config::ReadValues() { | |||
| 286 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem); | 286 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem); |
| 287 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); | 287 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); |
| 288 | ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); | 288 | ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); |
| 289 | ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts); | ||
| 289 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); | 290 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); |
| 290 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); | 291 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); |
| 291 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); | 292 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 5bbc3f532..6fcf04e1b 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -208,6 +208,10 @@ cpuopt_fastmem_exclusives = | |||
| 208 | # 0: Disabled, 1 (default): Enabled | 208 | # 0: Disabled, 1 (default): Enabled |
| 209 | cpuopt_recompile_exclusives = | 209 | cpuopt_recompile_exclusives = |
| 210 | 210 | ||
| 211 | # Enable optimization to ignore invalid memory accesses (faster guest memory access) | ||
| 212 | # 0: Disabled, 1 (default): Enabled | ||
| 213 | cpuopt_ignore_memory_aborts = | ||
| 214 | |||
| 211 | # Enable unfuse FMA (improve performance on CPUs without FMA) | 215 | # Enable unfuse FMA (improve performance on CPUs without FMA) |
| 212 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | 216 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. |
| 213 | # 0: Disabled, 1 (default): Enabled | 217 | # 0: Disabled, 1 (default): Enabled |