Memory: move Read/Write8/16/32/64 and ReadCString into class

This commit is contained in:
Weiyi Wang 2018-11-21 15:04:31 -05:00
parent 1ec9ed6827
commit 323990d402
11 changed files with 119 additions and 99 deletions

View file

@ -72,33 +72,34 @@ private:
class DynarmicUserCallbacks final : public Dynarmic::A32::UserCallbacks { class DynarmicUserCallbacks final : public Dynarmic::A32::UserCallbacks {
public: public:
explicit DynarmicUserCallbacks(ARM_Dynarmic& parent) explicit DynarmicUserCallbacks(ARM_Dynarmic& parent)
: parent(parent), timing(parent.system.CoreTiming()), svc_context(parent.system) {} : parent(parent), timing(parent.system.CoreTiming()), svc_context(parent.system),
memory(parent.system.Memory()) {}
~DynarmicUserCallbacks() = default; ~DynarmicUserCallbacks() = default;
std::uint8_t MemoryRead8(VAddr vaddr) override { std::uint8_t MemoryRead8(VAddr vaddr) override {
return Memory::Read8(vaddr); return memory.Read8(vaddr);
} }
std::uint16_t MemoryRead16(VAddr vaddr) override { std::uint16_t MemoryRead16(VAddr vaddr) override {
return Memory::Read16(vaddr); return memory.Read16(vaddr);
} }
std::uint32_t MemoryRead32(VAddr vaddr) override { std::uint32_t MemoryRead32(VAddr vaddr) override {
return Memory::Read32(vaddr); return memory.Read32(vaddr);
} }
std::uint64_t MemoryRead64(VAddr vaddr) override { std::uint64_t MemoryRead64(VAddr vaddr) override {
return Memory::Read64(vaddr); return memory.Read64(vaddr);
} }
void MemoryWrite8(VAddr vaddr, std::uint8_t value) override { void MemoryWrite8(VAddr vaddr, std::uint8_t value) override {
Memory::Write8(vaddr, value); memory.Write8(vaddr, value);
} }
void MemoryWrite16(VAddr vaddr, std::uint16_t value) override { void MemoryWrite16(VAddr vaddr, std::uint16_t value) override {
Memory::Write16(vaddr, value); memory.Write16(vaddr, value);
} }
void MemoryWrite32(VAddr vaddr, std::uint32_t value) override { void MemoryWrite32(VAddr vaddr, std::uint32_t value) override {
Memory::Write32(vaddr, value); memory.Write32(vaddr, value);
} }
void MemoryWrite64(VAddr vaddr, std::uint64_t value) override { void MemoryWrite64(VAddr vaddr, std::uint64_t value) override {
Memory::Write64(vaddr, value); memory.Write64(vaddr, value);
} }
void InterpreterFallback(VAddr pc, std::size_t num_instructions) override { void InterpreterFallback(VAddr pc, std::size_t num_instructions) override {
@ -159,6 +160,7 @@ public:
ARM_Dynarmic& parent; ARM_Dynarmic& parent;
Core::Timing& timing; Core::Timing& timing;
Kernel::SVCContext svc_context; Kernel::SVCContext svc_context;
Memory::MemorySystem& memory;
}; };
ARM_Dynarmic::ARM_Dynarmic(Core::System& system, PrivilegeMode initial_mode) ARM_Dynarmic::ARM_Dynarmic(Core::System& system, PrivilegeMode initial_mode)

View file

@ -811,7 +811,7 @@ MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,
ARM_INST_PTR& inst_base) { ARM_INST_PTR& inst_base) {
u32 inst_size = 4; u32 inst_size = 4;
u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC); u32 inst = Core::System::GetInstance().Memory().Read32(phys_addr & 0xFFFFFFFC);
// If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
// instruction // instruction

View file

@ -191,13 +191,13 @@ static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) {
u8 ARMul_State::ReadMemory8(u32 address) const { u8 ARMul_State::ReadMemory8(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
return Memory::Read8(address); return Core::System::GetInstance().Memory().Read8(address);
} }
u16 ARMul_State::ReadMemory16(u32 address) const { u16 ARMul_State::ReadMemory16(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
u16 data = Memory::Read16(address); u16 data = Core::System::GetInstance().Memory().Read16(address);
if (InBigEndianMode()) if (InBigEndianMode())
data = Common::swap16(data); data = Common::swap16(data);
@ -208,7 +208,7 @@ u16 ARMul_State::ReadMemory16(u32 address) const {
u32 ARMul_State::ReadMemory32(u32 address) const { u32 ARMul_State::ReadMemory32(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
u32 data = Memory::Read32(address); u32 data = Core::System::GetInstance().Memory().Read32(address);
if (InBigEndianMode()) if (InBigEndianMode())
data = Common::swap32(data); data = Common::swap32(data);
@ -219,7 +219,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const {
u64 ARMul_State::ReadMemory64(u32 address) const { u64 ARMul_State::ReadMemory64(u32 address) const {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
u64 data = Memory::Read64(address); u64 data = Core::System::GetInstance().Memory().Read64(address);
if (InBigEndianMode()) if (InBigEndianMode())
data = Common::swap64(data); data = Common::swap64(data);
@ -230,7 +230,7 @@ u64 ARMul_State::ReadMemory64(u32 address) const {
void ARMul_State::WriteMemory8(u32 address, u8 data) { void ARMul_State::WriteMemory8(u32 address, u8 data) {
CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
Memory::Write8(address, data); Core::System::GetInstance().Memory().Write8(address, data);
} }
void ARMul_State::WriteMemory16(u32 address, u16 data) { void ARMul_State::WriteMemory16(u32 address, u16 data) {
@ -239,7 +239,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data) {
if (InBigEndianMode()) if (InBigEndianMode())
data = Common::swap16(data); data = Common::swap16(data);
Memory::Write16(address, data); Core::System::GetInstance().Memory().Write16(address, data);
} }
void ARMul_State::WriteMemory32(u32 address, u32 data) { void ARMul_State::WriteMemory32(u32 address, u32 data) {
@ -248,7 +248,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data) {
if (InBigEndianMode()) if (InBigEndianMode())
data = Common::swap32(data); data = Common::swap32(data);
Memory::Write32(address, data); Core::System::GetInstance().Memory().Write32(address, data);
} }
void ARMul_State::WriteMemory64(u32 address, u64 data) { void ARMul_State::WriteMemory64(u32 address, u64 data) {
@ -257,7 +257,7 @@ void ARMul_State::WriteMemory64(u32 address, u64 data) {
if (InBigEndianMode()) if (InBigEndianMode())
data = Common::swap64(data); data = Common::swap64(data);
Memory::Write64(address, data); Core::System::GetInstance().Memory().Write64(address, data);
} }
// Reads from the CP15 registers. Used with implementation of the MRC instruction. // Reads from the CP15 registers. Used with implementation of the MRC instruction.

View file

@ -49,9 +49,10 @@ static inline std::enable_if_t<std::is_integral_v<T>> CompOp(const GatewayCheat:
} }
} }
static inline void LoadOffsetOp(const GatewayCheat::CheatLine& line, State& state) { static inline void LoadOffsetOp(Memory::MemorySystem& memory, const GatewayCheat::CheatLine& line,
State& state) {
u32 addr = line.address + state.offset; u32 addr = line.address + state.offset;
state.offset = Memory::Read32(addr); state.offset = memory.Read32(addr);
} }
static inline void LoopOp(const GatewayCheat::CheatLine& line, State& state) { static inline void LoopOp(const GatewayCheat::CheatLine& line, State& state) {
@ -154,7 +155,7 @@ static inline void PatchOp(const GatewayCheat::CheatLine& line, State& state, Co
state.current_line_nr++; state.current_line_nr++;
} }
first = !first; first = !first;
Memory::Write32(addr, tmp); system.Memory().Write32(addr, tmp);
addr += 4; addr += 4;
num_bytes -= 4; num_bytes -= 4;
} }
@ -162,7 +163,7 @@ static inline void PatchOp(const GatewayCheat::CheatLine& line, State& state, Co
u32 tmp = (first ? cheat_lines[state.current_line_nr].first u32 tmp = (first ? cheat_lines[state.current_line_nr].first
: cheat_lines[state.current_line_nr].value) >> : cheat_lines[state.current_line_nr].value) >>
bit_offset; bit_offset;
Memory::Write8(addr, tmp); system.Memory().Write8(addr, tmp);
addr += 1; addr += 1;
num_bytes -= 1; num_bytes -= 1;
bit_offset += 8; bit_offset += 8;
@ -205,6 +206,14 @@ GatewayCheat::~GatewayCheat() = default;
void GatewayCheat::Execute(Core::System& system) { void GatewayCheat::Execute(Core::System& system) {
State state; State state;
Memory::MemorySystem& memory = system.Memory();
auto Read8 = [&memory](VAddr addr) { return memory.Read8(addr); };
auto Read16 = [&memory](VAddr addr) { return memory.Read16(addr); };
auto Read32 = [&memory](VAddr addr) { return memory.Read32(addr); };
auto Write8 = [&memory](VAddr addr, u8 value) { memory.Write8(addr, value); };
auto Write16 = [&memory](VAddr addr, u16 value) { memory.Write16(addr, value); };
auto Write32 = [&memory](VAddr addr, u32 value) { memory.Write32(addr, value); };
for (state.current_line_nr = 0; state.current_line_nr < cheat_lines.size(); for (state.current_line_nr = 0; state.current_line_nr < cheat_lines.size();
state.current_line_nr++) { state.current_line_nr++) {
auto line = cheat_lines[state.current_line_nr]; auto line = cheat_lines[state.current_line_nr];
@ -247,63 +256,61 @@ void GatewayCheat::Execute(Core::System& system) {
break; break;
case CheatType::Write32: case CheatType::Write32:
// 0XXXXXXX YYYYYYYY - word[XXXXXXX+offset] = YYYYYYYY // 0XXXXXXX YYYYYYYY - word[XXXXXXX+offset] = YYYYYYYY
WriteOp<u32>(line, state, &Memory::Write32, system); WriteOp<u32>(line, state, Write32, system);
break; break;
case CheatType::Write16: case CheatType::Write16:
// 1XXXXXXX 0000YYYY - half[XXXXXXX+offset] = YYYY // 1XXXXXXX 0000YYYY - half[XXXXXXX+offset] = YYYY
WriteOp<u16>(line, state, &Memory::Write16, system); WriteOp<u16>(line, state, Write16, system);
break; break;
case CheatType::Write8: case CheatType::Write8:
// 2XXXXXXX 000000YY - byte[XXXXXXX+offset] = YY // 2XXXXXXX 000000YY - byte[XXXXXXX+offset] = YY
WriteOp<u8>(line, state, &Memory::Write8, system); WriteOp<u8>(line, state, Write8, system);
break; break;
case CheatType::GreaterThan32: case CheatType::GreaterThan32:
// 3XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY > word[XXXXXXX] ;unsigned // 3XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY > word[XXXXXXX] ;unsigned
CompOp<u32>(line, state, &Memory::Read32, CompOp<u32>(line, state, Read32, [&line](u32 val) -> bool { return line.value > val; });
[&line](u32 val) -> bool { return line.value > val; });
break; break;
case CheatType::LessThan32: case CheatType::LessThan32:
// 4XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY < word[XXXXXXX] ;unsigned // 4XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY < word[XXXXXXX] ;unsigned
CompOp<u32>(line, state, &Memory::Read32, CompOp<u32>(line, state, Read32, [&line](u32 val) -> bool { return line.value < val; });
[&line](u32 val) -> bool { return line.value < val; });
break; break;
case CheatType::EqualTo32: case CheatType::EqualTo32:
// 5XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY == word[XXXXXXX] ;unsigned // 5XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY == word[XXXXXXX] ;unsigned
CompOp<u32>(line, state, &Memory::Read32, CompOp<u32>(line, state, Read32,
[&line](u32 val) -> bool { return line.value == val; }); [&line](u32 val) -> bool { return line.value == val; });
break; break;
case CheatType::NotEqualTo32: case CheatType::NotEqualTo32:
// 6XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY != word[XXXXXXX] ;unsigned // 6XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY != word[XXXXXXX] ;unsigned
CompOp<u32>(line, state, &Memory::Read32, CompOp<u32>(line, state, Read32,
[&line](u32 val) -> bool { return line.value != val; }); [&line](u32 val) -> bool { return line.value != val; });
break; break;
case CheatType::GreaterThan16WithMask: case CheatType::GreaterThan16WithMask:
// 7XXXXXXX ZZZZYYYY - Execute next block IF YYYY > ((not ZZZZ) AND half[XXXXXXX]) // 7XXXXXXX ZZZZYYYY - Execute next block IF YYYY > ((not ZZZZ) AND half[XXXXXXX])
CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool { CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
return static_cast<u16>(line.value) > (static_cast<u16>(~line.value >> 16) & val); return static_cast<u16>(line.value) > (static_cast<u16>(~line.value >> 16) & val);
}); });
break; break;
case CheatType::LessThan16WithMask: case CheatType::LessThan16WithMask:
// 8XXXXXXX ZZZZYYYY - Execute next block IF YYYY < ((not ZZZZ) AND half[XXXXXXX]) // 8XXXXXXX ZZZZYYYY - Execute next block IF YYYY < ((not ZZZZ) AND half[XXXXXXX])
CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool { CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
return static_cast<u16>(line.value) < (static_cast<u16>(~line.value >> 16) & val); return static_cast<u16>(line.value) < (static_cast<u16>(~line.value >> 16) & val);
}); });
break; break;
case CheatType::EqualTo16WithMask: case CheatType::EqualTo16WithMask:
// 9XXXXXXX ZZZZYYYY - Execute next block IF YYYY = ((not ZZZZ) AND half[XXXXXXX]) // 9XXXXXXX ZZZZYYYY - Execute next block IF YYYY = ((not ZZZZ) AND half[XXXXXXX])
CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool { CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
return static_cast<u16>(line.value) == (static_cast<u16>(~line.value >> 16) & val); return static_cast<u16>(line.value) == (static_cast<u16>(~line.value >> 16) & val);
}); });
break; break;
case CheatType::NotEqualTo16WithMask: case CheatType::NotEqualTo16WithMask:
// AXXXXXXX ZZZZYYYY - Execute next block IF YYYY <> ((not ZZZZ) AND half[XXXXXXX]) // AXXXXXXX ZZZZYYYY - Execute next block IF YYYY <> ((not ZZZZ) AND half[XXXXXXX])
CompOp<u16>(line, state, &Memory::Read16, [&line](u16 val) -> bool { CompOp<u16>(line, state, Read16, [&line](u16 val) -> bool {
return static_cast<u16>(line.value) != (static_cast<u16>(~line.value >> 16) & val); return static_cast<u16>(line.value) != (static_cast<u16>(~line.value >> 16) & val);
}); });
break; break;
case CheatType::LoadOffset: case CheatType::LoadOffset:
// BXXXXXXX 00000000 - offset = word[XXXXXXX+offset] // BXXXXXXX 00000000 - offset = word[XXXXXXX+offset]
LoadOffsetOp(line, state); LoadOffsetOp(system.Memory(), line, state);
break; break;
case CheatType::Loop: { case CheatType::Loop: {
// C0000000 YYYYYYYY - LOOP next block YYYYYYYY times // C0000000 YYYYYYYY - LOOP next block YYYYYYYY times
@ -343,32 +350,32 @@ void GatewayCheat::Execute(Core::System& system) {
} }
case CheatType::IncrementiveWrite32: { case CheatType::IncrementiveWrite32: {
// D6000000 XXXXXXXX (32bit) [XXXXXXXX+offset] = reg ; offset += 4 // D6000000 XXXXXXXX (32bit) [XXXXXXXX+offset] = reg ; offset += 4
IncrementiveWriteOp<u32>(line, state, &Memory::Write32, system); IncrementiveWriteOp<u32>(line, state, Write32, system);
break; break;
} }
case CheatType::IncrementiveWrite16: { case CheatType::IncrementiveWrite16: {
// D7000000 XXXXXXXX (16bit) [XXXXXXXX+offset] = reg & 0xffff ; offset += 2 // D7000000 XXXXXXXX (16bit) [XXXXXXXX+offset] = reg & 0xffff ; offset += 2
IncrementiveWriteOp<u16>(line, state, &Memory::Write16, system); IncrementiveWriteOp<u16>(line, state, Write16, system);
break; break;
} }
case CheatType::IncrementiveWrite8: { case CheatType::IncrementiveWrite8: {
// D8000000 XXXXXXXX (16bit) [XXXXXXXX+offset] = reg & 0xff ; offset++ // D8000000 XXXXXXXX (16bit) [XXXXXXXX+offset] = reg & 0xff ; offset++
IncrementiveWriteOp<u8>(line, state, &Memory::Write8, system); IncrementiveWriteOp<u8>(line, state, Write8, system);
break; break;
} }
case CheatType::Load32: { case CheatType::Load32: {
// D9000000 XXXXXXXX reg = [XXXXXXXX+offset] // D9000000 XXXXXXXX reg = [XXXXXXXX+offset]
LoadOp<u32>(line, state, &Memory::Read32); LoadOp<u32>(line, state, Read32);
break; break;
} }
case CheatType::Load16: { case CheatType::Load16: {
// DA000000 XXXXXXXX reg = [XXXXXXXX+offset] & 0xFFFF // DA000000 XXXXXXXX reg = [XXXXXXXX+offset] & 0xFFFF
LoadOp<u16>(line, state, &Memory::Read16); LoadOp<u16>(line, state, Read16);
break; break;
} }
case CheatType::Load8: { case CheatType::Load8: {
// DB000000 XXXXXXXX reg = [XXXXXXXX+offset] & 0xFF // DB000000 XXXXXXXX reg = [XXXXXXXX+offset] & 0xFF
LoadOp<u8>(line, state, &Memory::Read8); LoadOp<u8>(line, state, Read8);
break; break;
} }
case CheatType::AddOffset: { case CheatType::AddOffset: {

View file

@ -65,7 +65,7 @@ SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
return thread; return thread;
} }
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel) {} AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
AddressArbiter::~AddressArbiter() {} AddressArbiter::~AddressArbiter() {}
SharedPtr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) { SharedPtr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
@ -103,31 +103,31 @@ ResultCode AddressArbiter::ArbitrateAddress(SharedPtr<Thread> thread, Arbitratio
// Wait current thread (acquire the arbiter)... // Wait current thread (acquire the arbiter)...
case ArbitrationType::WaitIfLessThan: case ArbitrationType::WaitIfLessThan:
if ((s32)Memory::Read32(address) < value) { if ((s32)kernel.memory.Read32(address) < value) {
WaitThread(std::move(thread), address); WaitThread(std::move(thread), address);
} }
break; break;
case ArbitrationType::WaitIfLessThanWithTimeout: case ArbitrationType::WaitIfLessThanWithTimeout:
if ((s32)Memory::Read32(address) < value) { if ((s32)kernel.memory.Read32(address) < value) {
thread->wakeup_callback = timeout_callback; thread->wakeup_callback = timeout_callback;
thread->WakeAfterDelay(nanoseconds); thread->WakeAfterDelay(nanoseconds);
WaitThread(std::move(thread), address); WaitThread(std::move(thread), address);
} }
break; break;
case ArbitrationType::DecrementAndWaitIfLessThan: { case ArbitrationType::DecrementAndWaitIfLessThan: {
s32 memory_value = Memory::Read32(address); s32 memory_value = kernel.memory.Read32(address);
if (memory_value < value) { if (memory_value < value) {
// Only change the memory value if the thread should wait // Only change the memory value if the thread should wait
Memory::Write32(address, (s32)memory_value - 1); kernel.memory.Write32(address, (s32)memory_value - 1);
WaitThread(std::move(thread), address); WaitThread(std::move(thread), address);
} }
break; break;
} }
case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: { case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: {
s32 memory_value = Memory::Read32(address); s32 memory_value = kernel.memory.Read32(address);
if (memory_value < value) { if (memory_value < value) {
// Only change the memory value if the thread should wait // Only change the memory value if the thread should wait
Memory::Write32(address, (s32)memory_value - 1); kernel.memory.Write32(address, (s32)memory_value - 1);
thread->wakeup_callback = timeout_callback; thread->wakeup_callback = timeout_callback;
thread->WakeAfterDelay(nanoseconds); thread->WakeAfterDelay(nanoseconds);
WaitThread(std::move(thread), address); WaitThread(std::move(thread), address);

View file

@ -52,6 +52,8 @@ private:
explicit AddressArbiter(KernelSystem& kernel); explicit AddressArbiter(KernelSystem& kernel);
~AddressArbiter() override; ~AddressArbiter() override;
KernelSystem& kernel;
/// Puts the thread to wait on the specified arbitration address under this address arbiter. /// Puts the thread to wait on the specified arbitration address under this address arbiter.
void WaitThread(SharedPtr<Thread> thread, VAddr wait_address); void WaitThread(SharedPtr<Thread> thread, VAddr wait_address);

View file

@ -352,7 +352,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
static constexpr std::size_t PortNameMaxLength = 11; static constexpr std::size_t PortNameMaxLength = 11;
// Read 1 char beyond the max allowed port name to detect names that are too long. // Read 1 char beyond the max allowed port name to detect names that are too long.
std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1); std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
if (port_name.size() > PortNameMaxLength) if (port_name.size() > PortNameMaxLength)
return ERR_PORT_NAME_TOO_LONG; return ERR_PORT_NAME_TOO_LONG;
@ -467,7 +467,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
std::vector<ObjectPtr> objects(handle_count); std::vector<ObjectPtr> objects(handle_count);
for (int i = 0; i < handle_count; ++i) { for (int i = 0; i < handle_count; ++i) {
Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
auto object = kernel.GetCurrentProcess()->handle_table.Get<WaitObject>(handle); auto object = kernel.GetCurrentProcess()->handle_table.Get<WaitObject>(handle);
if (object == nullptr) if (object == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -636,7 +636,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
SharedPtr<Process> current_process = kernel.GetCurrentProcess(); SharedPtr<Process> current_process = kernel.GetCurrentProcess();
for (int i = 0; i < handle_count; ++i) { for (int i = 0; i < handle_count; ++i) {
Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
auto object = current_process->handle_table.Get<WaitObject>(handle); auto object = current_process->handle_table.Get<WaitObject>(handle);
if (object == nullptr) if (object == nullptr)
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
@ -646,7 +646,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
// We are also sending a command reply. // We are also sending a command reply.
// Do not send a reply if the command id in the command buffer is 0xFFFF. // Do not send a reply if the command id in the command buffer is 0xFFFF.
Thread* thread = kernel.GetThreadManager().GetCurrentThread(); Thread* thread = kernel.GetThreadManager().GetCurrentThread();
u32 cmd_buff_header = Memory::Read32(thread->GetCommandBufferAddress()); u32 cmd_buff_header = memory.Read32(thread->GetCommandBufferAddress());
IPC::Header header{cmd_buff_header}; IPC::Header header{cmd_buff_header};
if (reply_target != 0 && header.command_id != 0xFFFF) { if (reply_target != 0 && header.command_id != 0xFFFF) {
auto session = current_process->handle_table.Get<ServerSession>(reply_target); auto session = current_process->handle_table.Get<ServerSession>(reply_target);
@ -832,9 +832,9 @@ ResultCode SVC::GetResourceLimitCurrentValues(VAddr values, Handle resource_limi
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
for (unsigned int i = 0; i < name_count; ++i) { for (unsigned int i = 0; i < name_count; ++i) {
u32 name = Memory::Read32(names + i * sizeof(u32)); u32 name = memory.Read32(names + i * sizeof(u32));
s64 value = resource_limit->GetCurrentResourceValue(name); s64 value = resource_limit->GetCurrentResourceValue(name);
Memory::Write64(values + i * sizeof(u64), value); memory.Write64(values + i * sizeof(u64), value);
} }
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -852,9 +852,9 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
for (unsigned int i = 0; i < name_count; ++i) { for (unsigned int i = 0; i < name_count; ++i) {
u32 name = Memory::Read32(names + i * sizeof(u32)); u32 name = memory.Read32(names + i * sizeof(u32));
s64 value = resource_limit->GetMaxResourceValue(name); s64 value = resource_limit->GetMaxResourceValue(name);
Memory::Write64(values + i * sizeof(u64), value); memory.Write64(values + i * sizeof(u64), value);
} }
return RESULT_SUCCESS; return RESULT_SUCCESS;

View file

@ -71,11 +71,11 @@ ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType reloc
break; break;
case RelocationType::AbsoluteAddress: case RelocationType::AbsoluteAddress:
case RelocationType::AbsoluteAddress2: case RelocationType::AbsoluteAddress2:
Memory::Write32(target_address, symbol_address + addend); memory.Write32(target_address, symbol_address + addend);
Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
break; break;
case RelocationType::RelativeAddress: case RelocationType::RelativeAddress:
Memory::Write32(target_address, symbol_address + addend - target_future_address); memory.Write32(target_address, symbol_address + addend - target_future_address);
Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
break; break;
case RelocationType::ThumbBranch: case RelocationType::ThumbBranch:
@ -98,7 +98,7 @@ ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType reloc
case RelocationType::AbsoluteAddress: case RelocationType::AbsoluteAddress:
case RelocationType::AbsoluteAddress2: case RelocationType::AbsoluteAddress2:
case RelocationType::RelativeAddress: case RelocationType::RelativeAddress:
Memory::Write32(target_address, 0); memory.Write32(target_address, 0);
Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); Core::CPU().InvalidateCacheRange(target_address, sizeof(u32));
break; break;
case RelocationType::ThumbBranch: case RelocationType::ThumbBranch:
@ -188,7 +188,7 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
ExportNamedSymbolEntry symbol_entry; ExportNamedSymbolEntry symbol_entry;
GetEntry(found_id, symbol_entry); GetEntry(found_id, symbol_entry);
if (Memory::ReadCString(symbol_entry.name_offset, export_strings_size) != name) if (memory.ReadCString(symbol_entry.name_offset, export_strings_size) != name)
return 0; return 0;
return SegmentTagToAddress(symbol_entry.symbol_position); return SegmentTagToAddress(symbol_entry.symbol_position);
@ -761,7 +761,7 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) {
ResultCode result = ForEachAutoLinkCRO( ResultCode result = ForEachAutoLinkCRO(
process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> { process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
std::string symbol_name = std::string symbol_name =
Memory::ReadCString(entry.name_offset, import_strings_size); memory.ReadCString(entry.name_offset, import_strings_size);
u32 symbol_address = source.FindExportNamedSymbol(symbol_name); u32 symbol_address = source.FindExportNamedSymbol(symbol_name);
if (symbol_address != 0) { if (symbol_address != 0) {
@ -858,7 +858,7 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
for (u32 i = 0; i < import_module_num; ++i) { for (u32 i = 0; i < import_module_num; ++i) {
ImportModuleEntry entry; ImportModuleEntry entry;
GetEntry(i, entry); GetEntry(i, entry);
std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); std::string want_cro_name = memory.ReadCString(entry.name_offset, import_strings_size);
ResultCode result = ForEachAutoLinkCRO( ResultCode result = ForEachAutoLinkCRO(
process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> { process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
@ -921,7 +921,7 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
if (!relocation_entry.is_batch_resolved) { if (!relocation_entry.is_batch_resolved) {
std::string symbol_name = std::string symbol_name =
Memory::ReadCString(entry.name_offset, target_import_strings_size); memory.ReadCString(entry.name_offset, target_import_strings_size);
u32 symbol_address = FindExportNamedSymbol(symbol_name); u32 symbol_address = FindExportNamedSymbol(symbol_name);
if (symbol_address != 0) { if (symbol_address != 0) {
LOG_TRACE(Service_LDR, " exports symbol \"{}\"", symbol_name); LOG_TRACE(Service_LDR, " exports symbol \"{}\"", symbol_name);
@ -952,7 +952,7 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
if (relocation_entry.is_batch_resolved) { if (relocation_entry.is_batch_resolved) {
std::string symbol_name = std::string symbol_name =
Memory::ReadCString(entry.name_offset, target_import_strings_size); memory.ReadCString(entry.name_offset, target_import_strings_size);
u32 symbol_address = FindExportNamedSymbol(symbol_name); u32 symbol_address = FindExportNamedSymbol(symbol_name);
if (symbol_address != 0) { if (symbol_address != 0) {
LOG_TRACE(Service_LDR, " unexports symbol \"{}\"", symbol_name); LOG_TRACE(Service_LDR, " unexports symbol \"{}\"", symbol_name);
@ -976,7 +976,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
ImportModuleEntry entry; ImportModuleEntry entry;
target.GetEntry(i, entry); target.GetEntry(i, entry);
if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name)
continue; continue;
LOG_INFO(Service_LDR, "CRO \"{}\" exports {} indexed symbols to \"{}\"", module_name, LOG_INFO(Service_LDR, "CRO \"{}\" exports {} indexed symbols to \"{}\"", module_name,
@ -1025,7 +1025,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
ImportModuleEntry entry; ImportModuleEntry entry;
target.GetEntry(i, entry); target.GetEntry(i, entry);
if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name)
continue; continue;
LOG_DEBUG(Service_LDR, "CRO \"{}\" unexports indexed symbols to \"{}\"", module_name, LOG_DEBUG(Service_LDR, "CRO \"{}\" unexports indexed symbols to \"{}\"", module_name,
@ -1069,7 +1069,7 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
Memory::ReadBlock(process, relocation_addr, &relocation_entry, Memory::ReadBlock(process, relocation_addr, &relocation_entry,
sizeof(ExternalRelocationEntry)); sizeof(ExternalRelocationEntry));
if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { if (memory.ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
ResultCode result = ForEachAutoLinkCRO( ResultCode result = ForEachAutoLinkCRO(
process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> { process, memory, crs_address, [&](CROHelper source) -> ResultVal<bool> {
u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_");
@ -1108,9 +1108,9 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
* @param size the size of the string (table), including the terminating 0 * @param size the size of the string (table), including the terminating 0
* @returns ResultCode RESULT_SUCCESS if the size matches, otherwise error code. * @returns ResultCode RESULT_SUCCESS if the size matches, otherwise error code.
*/ */
static ResultCode VerifyStringTableLength(VAddr address, u32 size) { static ResultCode VerifyStringTableLength(Memory::MemorySystem& memory, VAddr address, u32 size) {
if (size != 0) { if (size != 0) {
if (Memory::Read8(address + size - 1) != 0) if (memory.Read8(address + size - 1) != 0)
return CROFormatError(0x0B); return CROFormatError(0x0B);
} }
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -1126,7 +1126,7 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
return result; return result;
} }
result = VerifyStringTableLength(GetField(ModuleNameOffset), GetField(ModuleNameSize)); result = VerifyStringTableLength(memory, GetField(ModuleNameOffset), GetField(ModuleNameSize));
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error verifying module name {:08X}", result.raw); LOG_ERROR(Service_LDR, "Error verifying module name {:08X}", result.raw);
return result; return result;
@ -1155,7 +1155,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
return result; return result;
} }
result = VerifyStringTableLength(GetField(ExportStringsOffset), GetField(ExportStringsSize)); result =
VerifyStringTableLength(memory, GetField(ExportStringsOffset), GetField(ExportStringsSize));
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error verifying export strings {:08X}", result.raw); LOG_ERROR(Service_LDR, "Error verifying export strings {:08X}", result.raw);
return result; return result;
@ -1191,7 +1192,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment
return result; return result;
} }
result = VerifyStringTableLength(GetField(ImportStringsOffset), GetField(ImportStringsSize)); result =
VerifyStringTableLength(memory, GetField(ImportStringsOffset), GetField(ImportStringsSize));
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_LDR, "Error verifying import strings {:08X}", result.raw); LOG_ERROR(Service_LDR, "Error verifying import strings {:08X}", result.raw);
return result; return result;

View file

@ -44,7 +44,7 @@ public:
: module_address(cro_address), process(process), memory(memory) {} : module_address(cro_address), process(process), memory(memory) {}
std::string ModuleName() const { std::string ModuleName() const {
return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); return memory.ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize));
} }
u32 GetFileSize() const { u32 GetFileSize() const {
@ -408,11 +408,11 @@ private:
} }
u32 GetField(HeaderField field) const { u32 GetField(HeaderField field) const {
return Memory::Read32(Field(field)); return memory.Read32(Field(field));
} }
void SetField(HeaderField field, u32 value) { void SetField(HeaderField field, u32 value) {
Memory::Write32(Field(field), value); memory.Write32(Field(field), value);
} }
/** /**

View file

@ -114,7 +114,7 @@ template <typename T>
T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
template <typename T> template <typename T>
T Read(const VAddr vaddr) { T MemorySystem::Read(const VAddr vaddr) {
const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
if (page_pointer) { if (page_pointer) {
// NOTE: Avoid adding any extra logic to this fast-path block // NOTE: Avoid adding any extra logic to this fast-path block
@ -152,7 +152,7 @@ template <typename T>
void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
template <typename T> template <typename T>
void Write(const VAddr vaddr, const T data) { void MemorySystem::Write(const VAddr vaddr, const T data) {
u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
if (page_pointer) { if (page_pointer) {
// NOTE: Avoid adding any extra logic to this fast-path block // NOTE: Avoid adding any extra logic to this fast-path block
@ -224,7 +224,7 @@ u8* MemorySystem::GetPointer(const VAddr vaddr) {
return nullptr; return nullptr;
} }
std::string ReadCString(VAddr vaddr, std::size_t max_length) { std::string MemorySystem::ReadCString(VAddr vaddr, std::size_t max_length) {
std::string string; std::string string;
string.reserve(max_length); string.reserve(max_length);
for (std::size_t i = 0; i < max_length; ++i) { for (std::size_t i = 0; i < max_length; ++i) {
@ -417,19 +417,19 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR); CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR);
} }
u8 Read8(const VAddr addr) { u8 MemorySystem::Read8(const VAddr addr) {
return Read<u8>(addr); return Read<u8>(addr);
} }
u16 Read16(const VAddr addr) { u16 MemorySystem::Read16(const VAddr addr) {
return Read<u16_le>(addr); return Read<u16_le>(addr);
} }
u32 Read32(const VAddr addr) { u32 MemorySystem::Read32(const VAddr addr) {
return Read<u32_le>(addr); return Read<u32_le>(addr);
} }
u64 Read64(const VAddr addr) { u64 MemorySystem::Read64(const VAddr addr) {
return Read<u64_le>(addr); return Read<u64_le>(addr);
} }
@ -483,19 +483,19 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
} }
} }
void Write8(const VAddr addr, const u8 data) { void MemorySystem::Write8(const VAddr addr, const u8 data) {
Write<u8>(addr, data); Write<u8>(addr, data);
} }
void Write16(const VAddr addr, const u16 data) { void MemorySystem::Write16(const VAddr addr, const u16 data) {
Write<u16_le>(addr, data); Write<u16_le>(addr, data);
} }
void Write32(const VAddr addr, const u32 data) { void MemorySystem::Write32(const VAddr addr, const u32 data) {
Write<u32_le>(addr, data); Write<u32_le>(addr, data);
} }
void Write64(const VAddr addr, const u64 data) { void MemorySystem::Write64(const VAddr addr, const u64 data) {
Write<u64_le>(addr, data); Write<u64_le>(addr, data);
} }

View file

@ -180,16 +180,6 @@ enum : VAddr {
extern std::array<u8, Memory::FCRAM_N3DS_SIZE> fcram; extern std::array<u8, Memory::FCRAM_N3DS_SIZE> fcram;
u8 Read8(VAddr addr);
u16 Read16(VAddr addr);
u32 Read32(VAddr addr);
u64 Read64(VAddr addr);
void Write8(VAddr addr, u8 data);
void Write16(VAddr addr, u16 data);
void Write32(VAddr addr, u32 data);
void Write64(VAddr addr, u64 data);
void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, std::size_t size); void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, std::size_t size);
void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
std::size_t size); std::size_t size);
@ -198,8 +188,6 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process,
VAddr src_addr, VAddr dest_addr, std::size_t size); VAddr src_addr, VAddr dest_addr, std::size_t size);
std::string ReadCString(VAddr vaddr, std::size_t max_length);
/** /**
* Mark each page touching the region as cached. * Mark each page touching the region as cached.
*/ */
@ -241,6 +229,18 @@ public:
void SetCurrentPageTable(PageTable* page_table); void SetCurrentPageTable(PageTable* page_table);
PageTable* GetCurrentPageTable(); PageTable* GetCurrentPageTable();
u8 Read8(VAddr addr);
u16 Read16(VAddr addr);
u32 Read32(VAddr addr);
u64 Read64(VAddr addr);
void Write8(VAddr addr, u8 data);
void Write16(VAddr addr, u16 data);
void Write32(VAddr addr, u32 data);
void Write64(VAddr addr, u64 data);
std::string ReadCString(VAddr vaddr, std::size_t max_length);
/// Determines if the given VAddr is valid for the specified process. /// Determines if the given VAddr is valid for the specified process.
bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);
@ -255,6 +255,13 @@ public:
/// Gets offset in FCRAM from a pointer inside FCRAM range /// Gets offset in FCRAM from a pointer inside FCRAM range
u32 GetFCRAMOffset(u8* pointer); u32 GetFCRAMOffset(u8* pointer);
private:
template <typename T>
T Read(const VAddr vaddr);
template <typename T>
void Write(const VAddr vaddr, const T data);
}; };
} // namespace Memory } // namespace Memory