From 93668c24bebdf177edb506e2252bffb751fa07a8 Mon Sep 17 00:00:00 2001 From: Markus Wick Date: Tue, 31 Dec 2019 00:08:35 +0100 Subject: [PATCH] A64/x64: Create a global_offset optimization for the page table. Instead of looking up the page table like: table[addr >> 12][addr & 0xFFF] We can use a global offset on the table to query the memory like: table[addr >> 12][addr] This saves two instructions on *every* memory access within the recompiler. Thanks at skmp for the idea. --- include/dynarmic/A64/config.h | 7 +++++++ src/backend/x64/a64_emit_x64.cpp | 3 +++ 2 files changed, 10 insertions(+) diff --git a/include/dynarmic/A64/config.h b/include/dynarmic/A64/config.h index e1fd2f45..2b2a2463 100644 --- a/include/dynarmic/A64/config.h +++ b/include/dynarmic/A64/config.h @@ -163,6 +163,13 @@ struct UserConfig { /// relevant memory callback. /// This is only used if page_table is not nullptr. bool silently_mirror_page_table = true; + /// Determines if the pointer in the page_table shall be offseted locally or globally. + /// 'false' will access page_table[addr >> bits][addr & mask] + /// 'true' will access page_table[addr >> bits][addr] + /// Note: page_table[addr >> bits] will still be checked to verify active pages. + /// So there might be wrongly faulted pages which maps to nullptr. + /// This can be avoided by carefully allocating the memory region. + bool absolute_offset_page_table = false; /// This option relates to translation. Generally when we run into an unpredictable /// instruction the ExceptionRaised callback is called. If this is true, we define diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index ad90dd64..a45734f6 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -737,6 +737,9 @@ static Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, Xby code.mov(page_table, qword[page_table + tmp * sizeof(void*)]); code.test(page_table, page_table); code.jz(abort, code.T_NEAR); + if (ctx.conf.absolute_offset_page_table) { + return page_table + vaddr; + } code.mov(tmp, vaddr); code.and_(tmp, static_cast(page_size - 1)); return page_table + tmp;