mirror of
https://github.com/touchHLE/touchHLE.git
synced 2026-01-31 01:25:24 +01:00
Update dynarmic to HEAD
Allows for further work on dynarmic to be done (mainly to get LTO working) Also allows context register accesses from Rust code. Change-Id: If385a700daa806bc122eca937ec82b7ee2082a91
This commit is contained in:
20
src/cpu.rs
20
src/cpu.rs
@@ -17,6 +17,7 @@ use crate::mem::{ConstPtr, GuestUSize, Mem, MutPtr, Ptr, SafeRead, SafeWrite};
|
||||
use touchHLE_dynarmic_wrapper::*;
|
||||
|
||||
type VAddr = u32;
|
||||
pub type CpuContext = touchHLE_DynarmicContext;
|
||||
|
||||
fn touchHLE_cpu_read_impl<T: SafeRead + Default>(
|
||||
mem: *mut touchHLE_Mem,
|
||||
@@ -104,23 +105,6 @@ impl Drop for Cpu {
|
||||
}
|
||||
}
|
||||
|
||||
/// Object for storing the state of a CPU (registers etc), useful when switching
|
||||
/// threads.
|
||||
pub struct CpuContext {
|
||||
context: *mut Dynarmic_A32_Context,
|
||||
}
|
||||
impl CpuContext {
|
||||
pub fn new() -> Self {
|
||||
let context = unsafe { touchHLE_DynarmicWrapper_Context_new() };
|
||||
CpuContext { context }
|
||||
}
|
||||
}
|
||||
impl Drop for CpuContext {
|
||||
fn drop(&mut self) {
|
||||
unsafe { touchHLE_DynarmicWrapper_Context_delete(self.context) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Why CPU execution ended.
|
||||
#[derive(Debug)]
|
||||
pub enum CpuState {
|
||||
@@ -231,7 +215,7 @@ impl Cpu {
|
||||
/// Swap the current state of the CPU (registers etc) with the state stored
|
||||
/// in the context object.
|
||||
pub fn swap_context(&mut self, context: &mut CpuContext) {
|
||||
unsafe { touchHLE_DynarmicWrapper_swap_context(self.dynarmic_wrapper, context.context) }
|
||||
unsafe { touchHLE_DynarmicWrapper_swap_context(self.dynarmic_wrapper, context) }
|
||||
}
|
||||
|
||||
/// Get PC with the Thumb bit appropriately set.
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "dynarmic/interface/A32/a32.h"
|
||||
#include "dynarmic/interface/A32/config.h"
|
||||
#include "dynarmic/interface/A32/context.h"
|
||||
#include "dynarmic/interface/A32/coprocessor.h"
|
||||
#include "dynarmic/interface/exclusive_monitor.h"
|
||||
|
||||
@@ -27,6 +26,12 @@ bool touchHLE_cpu_write_u8(touchHLE_Mem *mem, VAddr addr, std::uint8_t value);
|
||||
bool touchHLE_cpu_write_u16(touchHLE_Mem *mem, VAddr addr, std::uint16_t value);
|
||||
bool touchHLE_cpu_write_u32(touchHLE_Mem *mem, VAddr addr, std::uint32_t value);
|
||||
bool touchHLE_cpu_write_u64(touchHLE_Mem *mem, VAddr addr, std::uint64_t value);
|
||||
struct touchHLE_DynarmicContext {
|
||||
std::array<std::uint32_t, 16> regs;
|
||||
std::array<std::uint32_t, 64> extregs;
|
||||
std::uint32_t cpsr;
|
||||
std::uint32_t fpscr;
|
||||
};
|
||||
}
|
||||
|
||||
const auto HaltReasonSvc = Dynarmic::HaltReason::UserDefined1;
|
||||
@@ -264,10 +269,14 @@ public:
|
||||
cpu->InvalidateCacheRange(start, size);
|
||||
}
|
||||
|
||||
void swap_context(void *context) {
|
||||
Dynarmic::A32::Context tmp = cpu->SaveContext();
|
||||
cpu->LoadContext(*(Dynarmic::A32::Context *)context);
|
||||
*(Dynarmic::A32::Context *)context = tmp;
|
||||
void swap_context(touchHLE_DynarmicContext *context) {
|
||||
touchHLE_DynarmicContext tmp = {cpu->Regs(), cpu->ExtRegs(), cpu->Cpsr(),
|
||||
cpu->Fpscr()};
|
||||
cpu->Regs() = context->regs;
|
||||
cpu->ExtRegs() = context->extregs;
|
||||
cpu->SetCpsr(context->cpsr);
|
||||
cpu->SetFpscr(context->fpscr);
|
||||
*context = tmp;
|
||||
}
|
||||
|
||||
std::int32_t run_or_step(touchHLE_Mem *mem, std::uint64_t *ticks) {
|
||||
@@ -327,7 +336,7 @@ void touchHLE_DynarmicWrapper_set_cpsr(DynarmicWrapper *cpu,
|
||||
}
|
||||
|
||||
void touchHLE_DynarmicWrapper_swap_context(DynarmicWrapper *cpu,
|
||||
void *context) {
|
||||
touchHLE_DynarmicContext *context) {
|
||||
cpu->swap_context(context);
|
||||
}
|
||||
|
||||
@@ -342,13 +351,6 @@ std::int32_t touchHLE_DynarmicWrapper_run_or_step(DynarmicWrapper *cpu,
|
||||
std::uint64_t *ticks) {
|
||||
return cpu->run_or_step(mem, ticks);
|
||||
}
|
||||
|
||||
void *touchHLE_DynarmicWrapper_Context_new() {
|
||||
return (void *)new Dynarmic::A32::Context();
|
||||
}
|
||||
void touchHLE_DynarmicWrapper_Context_delete(void *context) {
|
||||
delete (Dynarmic::A32::Context *)context;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace touchHLE::cpu
|
||||
|
||||
@@ -17,10 +17,33 @@ pub type touchHLE_DynarmicWrapper = std::ffi::c_void;
|
||||
/// `c_void` is used here to avoid depending on it directly)
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type touchHLE_Mem = std::ffi::c_void;
|
||||
/// Opaque C++ type
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type Dynarmic_A32_Context = std::ffi::c_void;
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
pub struct touchHLE_DynarmicContext {
|
||||
pub regs: [u32; 16],
|
||||
pub extregs: [u32; 64],
|
||||
pub cpsr: u32,
|
||||
pub fpscr: u32,
|
||||
}
|
||||
|
||||
impl Default for touchHLE_DynarmicContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
regs: [0; 16],
|
||||
extregs: [0; 64],
|
||||
cpsr: 0,
|
||||
fpscr: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl touchHLE_DynarmicContext {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
type VAddr = u32;
|
||||
|
||||
// Import functions from lib.cpp, see build.rs. Note that lib.cpp depends on
|
||||
@@ -37,7 +60,7 @@ extern "C" {
|
||||
pub fn touchHLE_DynarmicWrapper_set_cpsr(cpu: *mut touchHLE_DynarmicWrapper, cpsr: u32);
|
||||
pub fn touchHLE_DynarmicWrapper_swap_context(
|
||||
cpu: *mut touchHLE_DynarmicWrapper,
|
||||
context: *mut Dynarmic_A32_Context,
|
||||
context: *mut touchHLE_DynarmicContext,
|
||||
);
|
||||
pub fn touchHLE_DynarmicWrapper_invalidate_cache_range(
|
||||
cpu: *mut touchHLE_DynarmicWrapper,
|
||||
@@ -50,6 +73,4 @@ extern "C" {
|
||||
ticks: Option<&mut u64>,
|
||||
) -> i32;
|
||||
|
||||
pub fn touchHLE_DynarmicWrapper_Context_new() -> *mut Dynarmic_A32_Context;
|
||||
pub fn touchHLE_DynarmicWrapper_Context_delete(context: *mut Dynarmic_A32_Context);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ pub struct Thread {
|
||||
/// When a thread is currently executing, its state is stored directly in
|
||||
/// the CPU, rather than in a context object. In that case, this field is
|
||||
/// None. See also: [std::mem::take] and [cpu::Cpu::swap_context].
|
||||
context: Option<cpu::CpuContext>,
|
||||
context: Option<Box<cpu::CpuContext>>,
|
||||
/// Address range of this thread's stack, used to check if addresses are in
|
||||
/// range while producing a stack trace.
|
||||
stack: Option<std::ops::RangeInclusive<u32>>,
|
||||
@@ -721,25 +721,22 @@ impl Environment {
|
||||
return_value: None,
|
||||
in_start_routine: true,
|
||||
in_host_function: false,
|
||||
context: Some(cpu::CpuContext::new()),
|
||||
context: Some(Box::new(cpu::CpuContext::new())),
|
||||
stack: Some(stack_alloc.to_bits()..=(stack_high_addr - 1)),
|
||||
});
|
||||
let new_thread_id = self.threads.len() - 1;
|
||||
|
||||
log_dbg!("Created new thread {} with stack {:#x}–{:#x}, will execute function {:?} with data {:?}", new_thread_id, stack_alloc.to_bits(), (stack_high_addr - 1), start_routine, user_data);
|
||||
|
||||
let old_thread = self.current_thread;
|
||||
// Set up the registers for the new thread
|
||||
let context = self.threads[new_thread_id].context.as_mut().unwrap();
|
||||
context.regs[cpu::Cpu::SP] = stack_high_addr;
|
||||
context.regs[0] = user_data.to_bits();
|
||||
|
||||
// Switch to the new context (all zeroes) and set up the registers
|
||||
// (which we can only do by switching). The original thread's state
|
||||
// should be the same as before.
|
||||
self.switch_thread(new_thread_id);
|
||||
self.cpu.set_cpsr(cpu::Cpu::CPSR_USER_MODE);
|
||||
self.cpu.regs_mut()[cpu::Cpu::SP] = stack_high_addr;
|
||||
self.cpu.regs_mut()[0] = user_data.to_bits();
|
||||
self.cpu
|
||||
.branch_with_link(start_routine, self.dyld.thread_exit_routine());
|
||||
self.switch_thread(old_thread);
|
||||
context.cpsr =
|
||||
cpu::Cpu::CPSR_USER_MODE | ((start_routine.is_thumb() as u32) * cpu::Cpu::CPSR_THUMB);
|
||||
context.regs[cpu::Cpu::PC] = start_routine.addr_without_thumb_bit();
|
||||
context.regs[cpu::Cpu::LR] = self.dyld.thread_exit_routine().addr_with_thumb_bit();
|
||||
|
||||
new_thread_id
|
||||
}
|
||||
|
||||
2
vendor/dynarmic
vendored
2
vendor/dynarmic
vendored
Submodule vendor/dynarmic updated: 76aa4dd665...a41c380246
Reference in New Issue
Block a user