mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-18 10:39:00 +02:00
[dynarmic, common] pagetable clustering (#3215)
Raises the size of each page entry to 32 bytes, however, it merges them into a single structure THEORETICALLY this is better since the access pattern observed corresponds to the program wanting backing_addr/pointers/blocks immediately after one another. This may improve performance at the cost of some extra memory. Another implementation would be to structure only backing_addr/blocks within the same virtual buffer. Alas spamming virtual buffers is evil since each of them is a cache trasher (imagine jumping from wildly different block to wildly different block immediately). Signed-off-by: lizzie lizzie@eden-emu.dev Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3215 Reviewed-by: DraVee <dravee@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
1cb8bcf531
commit
dceeccd04b
13 changed files with 103 additions and 108 deletions
|
|
@ -372,6 +372,7 @@ EmitConfig A32AddressSpace::GetEmitConfig() {
|
|||
.page_table_pointer = std::bit_cast<u64>(conf.page_table),
|
||||
.page_table_address_space_bits = 32,
|
||||
.page_table_pointer_mask_bits = conf.page_table_pointer_mask_bits,
|
||||
.page_table_log2_stride = conf.page_table_log2_stride,
|
||||
.silently_mirror_page_table = true,
|
||||
.absolute_offset_page_table = conf.absolute_offset_page_table,
|
||||
.detect_misaligned_access_via_page_table = conf.detect_misaligned_access_via_page_table,
|
||||
|
|
|
|||
|
|
@ -547,6 +547,7 @@ EmitConfig A64AddressSpace::GetEmitConfig() {
|
|||
.page_table_pointer = std::bit_cast<u64>(conf.page_table),
|
||||
.page_table_address_space_bits = conf.page_table_address_space_bits,
|
||||
.page_table_pointer_mask_bits = conf.page_table_pointer_mask_bits,
|
||||
.page_table_log2_stride = conf.page_table_log2_stride,
|
||||
.silently_mirror_page_table = conf.silently_mirror_page_table,
|
||||
.absolute_offset_page_table = conf.absolute_offset_page_table,
|
||||
.detect_misaligned_access_via_page_table = conf.detect_misaligned_access_via_page_table,
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ struct EmitConfig {
|
|||
u64 page_table_pointer;
|
||||
size_t page_table_address_space_bits;
|
||||
int page_table_pointer_mask_bits;
|
||||
size_t page_table_log2_stride;
|
||||
bool silently_mirror_page_table;
|
||||
bool absolute_offset_page_table;
|
||||
u8 detect_misaligned_access_via_page_table;
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ std::pair<oaknut::XReg, oaknut::XReg> InlinePageTableEmitVAddrLookup(oaknut::Cod
|
|||
code.B(NE, *fallback);
|
||||
}
|
||||
|
||||
code.LDR(Xscratch0, Xpagetable, Xscratch0, LSL, 3);
|
||||
code.LDR(Xscratch0, Xpagetable, Xscratch0, LSL, ctx.conf.page_table_log2_stride);
|
||||
|
||||
if (ctx.conf.page_table_pointer_mask_bits != 0) {
|
||||
const u64 mask = u64(~u64(0)) << ctx.conf.page_table_pointer_mask_bits;
|
||||
|
|
|
|||
|
|
@ -83,9 +83,9 @@ template<>
|
|||
// TODO: This code assumes vaddr has been zext from 32-bits to 64-bits.
|
||||
|
||||
code.mov(tmp, vaddr.cvt32());
|
||||
code.shr(tmp, static_cast<int>(page_bits));
|
||||
|
||||
code.mov(page, qword[r14 + tmp.cvt64() * sizeof(void*)]);
|
||||
code.shr(tmp, int(page_bits));
|
||||
code.shl(tmp, int(ctx.conf.page_table_log2_stride));
|
||||
code.mov(page, qword[r14 + tmp.cvt64()]);
|
||||
if (ctx.conf.page_table_pointer_mask_bits == 0) {
|
||||
code.test(page, page);
|
||||
} else {
|
||||
|
|
@ -138,7 +138,9 @@ template<>
|
|||
code.test(tmp, u32(-(1 << valid_page_index_bits)));
|
||||
code.jnz(abort, code.T_NEAR);
|
||||
}
|
||||
code.mov(page, qword[r14 + tmp * sizeof(void*)]);
|
||||
|
||||
code.shl(tmp, int(ctx.conf.page_table_log2_stride));
|
||||
code.mov(page, qword[r14 + tmp]);
|
||||
if (ctx.conf.page_table_pointer_mask_bits == 0) {
|
||||
code.test(page, page);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -168,6 +168,9 @@ struct UserConfig {
|
|||
/// If the configured value is 3, all pointers will be forcefully aligned to 8 bytes.
|
||||
std::int32_t page_table_pointer_mask_bits = 0;
|
||||
|
||||
// Log2 of the size per page entry, value should be either 3 or 4
|
||||
std::size_t page_table_log2_stride = 3;
|
||||
|
||||
/// Select the architecture version to use.
|
||||
/// There are minor behavioural differences between versions.
|
||||
ArchVersion arch_version = ArchVersion::v8;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -179,6 +182,9 @@ struct UserConfig {
|
|||
/// If the configured value is 3, all pointers will be forcefully aligned to 8 bytes.
|
||||
std::int32_t page_table_pointer_mask_bits = 0;
|
||||
|
||||
// Log2 of the size per page entry, value should be either 3 or 4
|
||||
std::size_t page_table_log2_stride = 3;
|
||||
|
||||
/// Counter-timer frequency register. The value of the register is not interpreted by
|
||||
/// dynarmic.
|
||||
std::uint32_t cntfrq_el0 = 600000000;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue