aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp27
-rw-r--r--src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp28
-rw-r--r--src/dynarmic/src/dynarmic/backend/x64/abi.cpp6
-rw-r--r--src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp2
-rw-r--r--src/dynarmic/tests/print_info.cpp23
-rwxr-xr-xtools/dtrace-tool.sh59
7 files changed, 55 insertions, 92 deletions
diff --git a/.gitignore b/.gitignore
index d070d94681..0be76d85cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,8 @@ CMakeLists.txt.user*
# *nix related
# Common convention for backup or temporary files
*~
+*.core
+dtrace-out/
# Visual Studio CMake settings
CMakeSettings.json
diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
index 90d9b73e08..986a6659b1 100644
--- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
+++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
@@ -217,13 +217,13 @@ void A32EmitX64::ClearFastDispatchTable() {
}
void A32EmitX64::GenTerminalHandlers() {
- // PC ends up in ebp, location_descriptor ends up in rbx
+ // PC ends up in edi, location_descriptor ends up in rbx
const auto calculate_location_descriptor = [this] {
// This calculation has to match up with IREmitter::PushRSB
code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)]);
code.shl(rbx, 32);
code.mov(ecx, MJitStateReg(A32::Reg::PC));
- code.mov(ebp, ecx);
+ code.mov(edi, ecx);
code.or_(rbx, rcx);
};
@@ -238,7 +238,7 @@ void A32EmitX64::GenTerminalHandlers() {
code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)], eax);
code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
- code.jne(rsb_cache_miss);
+ code.jne(rsb_cache_miss, code.T_NEAR);
} else {
code.jne(code.GetReturnFromRunCodeAddress());
}
@@ -251,20 +251,21 @@ void A32EmitX64::GenTerminalHandlers() {
terminal_handler_fast_dispatch_hint = code.getCurr<const void*>();
calculate_location_descriptor();
code.L(rsb_cache_miss);
- code.mov(r12, reinterpret_cast<u64>(fast_dispatch_table.data()));
- code.mov(rbp, rbx);
+ code.mov(r8, reinterpret_cast<u64>(fast_dispatch_table.data()));
+ //code.mov(r12d, MJitStateReg(A32::Reg::PC));
+ code.mov(r12, rbx);
if (code.HasHostFeature(HostFeature::SSE42)) {
- code.crc32(rbp, r12);
+ code.crc32(r12, r8);
}
- code.and_(ebp, fast_dispatch_table_mask);
- code.lea(rbp, ptr[r12 + rbp]);
- code.cmp(rbx, qword[rbp + offsetof(FastDispatchEntry, location_descriptor)]);
- code.jne(fast_dispatch_cache_miss);
- code.jmp(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)]);
+ code.and_(r12d, fast_dispatch_table_mask);
+ code.lea(r12, ptr[r8 + r12]);
+ code.cmp(rbx, qword[r12 + offsetof(FastDispatchEntry, location_descriptor)]);
+ code.jne(fast_dispatch_cache_miss, code.T_NEAR);
+ code.jmp(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)]);
code.L(fast_dispatch_cache_miss);
- code.mov(qword[rbp + offsetof(FastDispatchEntry, location_descriptor)], rbx);
+ code.mov(qword[r12 + offsetof(FastDispatchEntry, location_descriptor)], rbx);
code.LookupBlock();
- code.mov(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)], rax);
+ code.mov(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)], rax);
code.jmp(rax);
PerfMapRegister(terminal_handler_fast_dispatch_hint, code.getCurr(), "a32_terminal_handler_fast_dispatch_hint");
diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
index 9090285a7d..044249a26b 100644
--- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
+++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
@@ -188,13 +188,14 @@ void A64EmitX64::ClearFastDispatchTable() {
}
void A64EmitX64::GenTerminalHandlers() {
- // PC ends up in rbp, location_descriptor ends up in rbx
+ // PC ends up in rcx, location_descriptor ends up in rbx
+ static_assert(std::find(ABI_ALL_CALLEE_SAVE.begin(), ABI_ALL_CALLEE_SAVE.end(), HostLoc::R12) != ABI_ALL_CALLEE_SAVE.end());
const auto calculate_location_descriptor = [this] {
// This calculation has to match up with A64::LocationDescriptor::UniqueHash
// TODO: Optimization is available here based on known state of fpcr.
- code.mov(rbp, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
+ code.mov(rdi, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
code.mov(rcx, A64::LocationDescriptor::pc_mask);
- code.and_(rcx, rbp);
+ code.and_(rcx, rdi);
code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A64JitState, fpcr)]);
code.and_(ebx, A64::LocationDescriptor::fpcr_mask);
code.shl(rbx, A64::LocationDescriptor::fpcr_shift);
@@ -226,20 +227,21 @@ void A64EmitX64::GenTerminalHandlers() {
terminal_handler_fast_dispatch_hint = code.getCurr<const void*>();
calculate_location_descriptor();
code.L(rsb_cache_miss);
- code.mov(r12, reinterpret_cast<u64>(fast_dispatch_table.data()));
- code.mov(rbp, rbx);
+ code.mov(r8, reinterpret_cast<u64>(fast_dispatch_table.data()));
+ //code.mov(r12, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
+ code.mov(r12, rbx);
if (code.HasHostFeature(HostFeature::SSE42)) {
- code.crc32(rbp, r12);
+ code.crc32(r12, r8);
}
- code.and_(ebp, fast_dispatch_table_mask);
- code.lea(rbp, ptr[r12 + rbp]);
- code.cmp(rbx, qword[rbp + offsetof(FastDispatchEntry, location_descriptor)]);
- code.jne(fast_dispatch_cache_miss);
- code.jmp(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)]);
+ code.and_(r12d, fast_dispatch_table_mask);
+ code.lea(r12, ptr[r8 + r12]);
+ code.cmp(rbx, qword[r12 + offsetof(FastDispatchEntry, location_descriptor)]);
+ code.jne(fast_dispatch_cache_miss, code.T_NEAR);
+ code.jmp(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)]);
code.L(fast_dispatch_cache_miss);
- code.mov(qword[rbp + offsetof(FastDispatchEntry, location_descriptor)], rbx);
+ code.mov(qword[r12 + offsetof(FastDispatchEntry, location_descriptor)], rbx);
code.LookupBlock();
- code.mov(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)], rax);
+ code.mov(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)], rax);
code.jmp(rax);
PerfMapRegister(terminal_handler_fast_dispatch_hint, code.getCurr(), "a64_terminal_handler_fast_dispatch_hint");
diff --git a/src/dynarmic/src/dynarmic/backend/x64/abi.cpp b/src/dynarmic/src/dynarmic/backend/x64/abi.cpp
index 299bf1d1d6..f64dbe3fa8 100644
--- a/src/dynarmic/src/dynarmic/backend/x64/abi.cpp
+++ b/src/dynarmic/src/dynarmic/backend/x64/abi.cpp
@@ -28,7 +28,8 @@ static_assert(ABI_SHADOW_SPACE <= 32);
static FrameInfo CalculateFrameInfo(const size_t num_gprs, const size_t num_xmms, size_t frame_size) {
// We are initially 8 byte aligned because the return value is pushed onto an aligned stack after a call.
- const size_t rsp_alignment = (num_gprs % 2 == 0) ? 8 : 0;
+ // (It's an extra GPR save due to %rbp)
+ const size_t rsp_alignment = ((num_gprs + 1) % 2 == 0) ? 8 : 0;
const size_t total_xmm_size = num_xmms * XMM_SIZE;
if (frame_size & 0xF) {
frame_size += 0x10 - (frame_size & 0xF);
@@ -48,6 +49,8 @@ void ABI_PushRegistersAndAdjustStack(BlockOfCode& code, const size_t frame_size,
const size_t num_xmms = std::count_if(regs.begin(), regs.end(), HostLocIsXMM);
const FrameInfo frame_info = CalculateFrameInfo(num_gprs, num_xmms, frame_size);
+ code.push(rbp);
+ code.mov(rbp, rsp);
for (auto const gpr : regs)
if (HostLocIsGPR(gpr))
code.push(HostLocToReg64(gpr));
@@ -93,6 +96,7 @@ void ABI_PopRegistersAndAdjustStack(BlockOfCode& code, const size_t frame_size,
if (HostLocIsGPR(gpr))
code.pop(HostLocToReg64(gpr));
}
+ code.pop(rbp);
}
void ABI_PushCalleeSaveRegistersAndAdjustStack(BlockOfCode& code, const std::size_t frame_size) {
diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
index 8bf3707674..52033b953e 100644
--- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
+++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
@@ -370,7 +370,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
cmp(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], 0);
jne(return_to_caller_mxcsr_already_exited, T_NEAR);
- lock(); or_(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], static_cast<u32>(HaltReason::Step));
+ lock(); or_(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], u32(HaltReason::Step));
SwitchMxcsrOnEntry();
jmp(ABI_PARAM2);
diff --git a/src/dynarmic/tests/print_info.cpp b/src/dynarmic/tests/print_info.cpp
index 8936f32bd3..327a257b83 100644
--- a/src/dynarmic/tests/print_info.cpp
+++ b/src/dynarmic/tests/print_info.cpp
@@ -37,6 +37,9 @@
#include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/opt_passes.h"
+#include "./A32/testenv.h"
+#include "./A64/testenv.h"
+
using namespace Dynarmic;
std::string_view GetNameOfA32Instruction(u32 instruction) {
@@ -65,7 +68,10 @@ void PrintA32Instruction(u32 instruction) {
fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
- Optimization::Optimize(ir_block, A32::UserConfig{}, {});
+ ArmTestEnv jit_env{};
+ Dynarmic::A32::UserConfig jit_user_config{};
+ jit_user_config.callbacks = &jit_env;
+ Optimization::Optimize(ir_block, jit_user_config, {});
fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
}
@@ -80,7 +86,10 @@ void PrintA64Instruction(u32 instruction) {
fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
- Optimization::Optimize(ir_block, A64::UserConfig{}, {});
+ A64TestEnv jit_env{};
+ Dynarmic::A64::UserConfig jit_user_config{};
+ jit_user_config.callbacks = &jit_env;
+ Optimization::Optimize(ir_block, jit_user_config, {});
fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
}
@@ -98,7 +107,10 @@ void PrintThumbInstruction(u32 instruction) {
fmt::print("should_continue: {}\n\n", should_continue);
fmt::print("IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
- Optimization::Optimize(ir_block, A32::UserConfig{}, {});
+ ThumbTestEnv jit_env{};
+ Dynarmic::A32::UserConfig jit_user_config{};
+ jit_user_config.callbacks = &jit_env;
+ Optimization::Optimize(ir_block, jit_user_config, {});
fmt::print("Optimized IR:\n");
fmt::print("{}\n", IR::DumpBlock(ir_block));
}
@@ -219,7 +231,7 @@ void ExecuteA32Instruction(u32 instruction) {
*(iter->second) = *value;
fmt::print("> {} = 0x{:08x}\n", reg_name, *value);
}
- } else if (reg_name == "mem" || reg_name == "memory") {
+ } else if (reg_name.starts_with("m")) {
fmt::print("address: ");
if (const auto address = get_value()) {
fmt::print("value: ");
@@ -228,7 +240,7 @@ void ExecuteA32Instruction(u32 instruction) {
fmt::print("> mem[0x{:08x}] = 0x{:08x}\n", *address, *value);
}
}
- } else if (reg_name == "end") {
+ } else if (reg_name == "exit" || reg_name == "end" || reg_name.starts_with("q")) {
break;
}
}
@@ -244,6 +256,7 @@ void ExecuteA32Instruction(u32 instruction) {
env.MemoryWrite32(initial_pc + 4, 0xEAFFFFFE); // B +0
cpu.Run();
+ fmt::print("{}", fmt::join(cpu.Disassemble(), "\n"));
fmt::print("Registers modified:\n");
for (size_t i = 0; i < regs.size(); ++i) {
diff --git a/tools/dtrace-tool.sh b/tools/dtrace-tool.sh
deleted file mode 100755
index 4a75848fcd..0000000000
--- a/tools/dtrace-tool.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/local/bin/bash -ex
-
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-# Basic script to run dtrace sampling over the program (requires Flamegraph)
-# Usage is either running as: ./dtrace-tool.sh pid (then input the pid of the process)
-# Or just run directly with: ./dtrace-tool.sh <command>
-
-FLAMEGRAPH_DIR=".."
-fail() {
- printf '%s\n' "$1" >&2
- exit "${2-1}"
-}
-
-[ -f $FLAMEGRAPH_DIR/FlameGraph/stackcollapse.pl ] || fail 'Where is flamegraph?'
-#[ which dtrace ] || fail 'Needs DTrace installed'
-
-read -r "Sampling Hz [800]: " TRACE_CFG_HZ
-if [ -z "${TRACE_CFG_HZ}" ]; then
- TRACE_CFG_HZ=800
-fi
-
-read -r "Sampling time [5] sec: " TRACE_CFG_TIME
-if [ -z "${TRACE_CFG_TIME}" ]; then
- TRACE_CFG_TIME=5
-fi
-
-TRACE_FILE=dtrace-out.user_stacks
-TRACE_FOLD=dtrace-out.fold
-TRACE_SVG=dtrace-out.svg
-ps
-
-if [ "$1" = 'pid' ]; then
- read -r "PID: " TRACE_CFG_PID
- sudo echo 'Sudo!'
-else
- if [ -f "$1" ] && [ "$1" ]; then
- fail 'Usage: ./tools/dtrace-profile.sh <path to program>'
- fi
-
- printf "Executing: "
- echo "$@"
- sudo echo 'Sudo!'
- "$@" &
- TRACE_CFG_PID=$!
-fi
-
-TRACE_PROBE="profile-${TRACE_CFG_HZ} /pid == ${TRACE_CFG_PID} && arg1/ { @[ustack()] = count(); } tick-${TRACE_CFG_TIME}s { exit(0); }"
-
-rm -- $TRACE_SVG || echo 'Skip'
-
-sudo dtrace -x ustackframes=100 -Z -n "$TRACE_PROBE" -o $TRACE_FILE 2>/dev/null || exit
-
-perl $FLAMEGRAPH_DIR/FlameGraph/stackcollapse.pl $TRACE_FILE > $TRACE_FOLD || exit
-perl $FLAMEGRAPH_DIR/FlameGraph/flamegraph.pl $TRACE_FOLD > $TRACE_SVG || exit
-
-sudo chmod 0666 $TRACE_FILE
-rm -- $TRACE_FILE $TRACE_FOLD \ No newline at end of file