From 4a3cd024ed24090867bb9502ffd0ec950429c90c Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 30 Nov 2003 17:21:53 +0000 Subject: [PATCH] better handling of static translation cache allocation, handle nested execution paths from the cpu core, cleanups for KPX_MAX_CPUS == 1. --- SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp | 11 +---- .../src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp | 4 +- .../src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp | 2 +- .../src/kpx_cpu/src/cpu/jit/jit-cache.cpp | 44 ++++++++++++++----- .../src/kpx_cpu/src/cpu/jit/jit-cache.hpp | 8 ++-- .../src/kpx_cpu/src/cpu/ppc/ppc-config.hpp | 17 +------ .../src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp | 21 +++++---- .../src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp | 10 +++-- .../src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp | 4 +- 9 files changed, 62 insertions(+), 59 deletions(-) diff --git a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp index cb315333..a7e86d68 100644 --- a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp +++ b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp @@ -118,9 +118,6 @@ public: uint32 get_cr() const { return cr().get(); } void set_cr(uint32 v) { cr().set(v); } - // Execution loop - void execute(uint32 entry, bool enable_cache = false); - // Execute 68k routine void execute_68k(uint32 entry, M68kRegisters *r); @@ -244,12 +241,6 @@ void sheepshaver_cpu::execute_sheep(uint32 opcode) } } -// Execution loop -void sheepshaver_cpu::execute(uint32 entry, bool enable_cache) -{ - powerpc_cpu::execute(entry, enable_cache); -} - // Handle MacOS interrupt void sheepshaver_cpu::interrupt(uint32 entry) { @@ -686,7 +677,7 @@ void emul_ppc(uint32 entry) current_cpu->start_log(); #endif // start emulation loop and enable code translation or caching - current_cpu->execute(entry, true); + current_cpu->execute(entry); } /* diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp index 999c5357..3b3d54da 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp @@ -28,8 +28,8 @@ int __op_jmp0, __op_jmp1; #define DEFINE_GEN(NAME,ARGS) void basic_dyngen::NAME ARGS #include "basic-dyngen-ops.hpp" -basic_dyngen::basic_dyngen(dyngen_cpu_base cpu) - : parent_cpu(cpu) +basic_dyngen::basic_dyngen(dyngen_cpu_base cpu, int cache_size) + : parent_cpu(cpu), basic_jit_cache(cache_size) { execute_func = gen_start(); gen_op_execute(); diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp index 8c136f63..81278f4d 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp @@ -52,7 +52,7 @@ class basic_dyngen public: // Constructor, parent CPU required - basic_dyngen(dyngen_cpu_base cpu); + basic_dyngen(dyngen_cpu_base cpu, int cache_size = -1); // Return CPU context associated to this code generator dyngen_cpu_base cpu() const diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp index 9f6014ee..9bc2ad37 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp @@ -30,10 +30,13 @@ #endif #if STATIC_ICACHE_ALLOC -static uint8 g_translation_cache[basic_jit_cache::JIT_CACHE_SIZE]; +const int G_TRANSLATION_CACHE_SIZE = 3 * 1024 * 1024; // 3 MB +static uint8 g_translation_cache[G_TRANSLATION_CACHE_SIZE]; +static uint8 *g_translation_cache_p; +static uint8 *g_translation_cache_end_p; #endif -basic_jit_cache::basic_jit_cache(uint32 init_cache_size) +basic_jit_cache::basic_jit_cache(int init_cache_size) : tcode_start(NULL), code_start(NULL), code_p(NULL), code_end(NULL) { init_translation_cache(init_cache_size); @@ -45,16 +48,27 @@ basic_jit_cache::~basic_jit_cache() } bool -basic_jit_cache::init_translation_cache(uint32 size) +basic_jit_cache::init_translation_cache(int size) { - // Round up translation cache size to next 16 KB boundaries - const uint32 roundup = 16 * 1024; - uint32 effective_cache_size = (size - JIT_CACHE_SIZE_GUARD) & -roundup; - cache_size = size & -roundup; +#if STATIC_ICACHE_ALLOC + if (g_translation_cache_p == 0) { + g_translation_cache_p = g_translation_cache; + g_translation_cache_end_p = g_translation_cache_p + G_TRANSLATION_CACHE_SIZE; + } +#endif + + if (size == -1) + size = JIT_CACHE_SIZE; + + // Round up translation cache size to next guard size boundaries boundaries + const uint32 roundup = JIT_CACHE_SIZE_GUARD; + cache_size = (size + roundup - 1) & -roundup; + assert(cache_size > 0); #if STATIC_ICACHE_ALLOC - if (cache_size <= JIT_CACHE_SIZE) { - tcode_start = g_translation_cache; + if (cache_size <= (g_translation_cache_end_p - g_translation_cache_p)) { + tcode_start = g_translation_cache_p; + g_translation_cache_p += cache_size; goto done; } #endif @@ -75,7 +89,7 @@ basic_jit_cache::init_translation_cache(uint32 size) D(bug("basic_jit_cache: Translation cache: %d KB at %p\n", cache_size / 1024, tcode_start)); code_start = tcode_start; code_p = code_start; - code_end = code_p + effective_cache_size; + code_end = code_p + size; return true; } @@ -84,8 +98,16 @@ basic_jit_cache::kill_translation_cache() { if (tcode_start) { #if STATIC_ICACHE_ALLOC - if (cache_size > JIT_CACHE_SIZE) + if ((tcode_start - g_translation_cache) <= G_TRANSLATION_CACHE_SIZE) { + if (tcode_start == g_translation_cache_p - cache_size) { + D(bug("basic_jit_cache: Merge back free translation cache: %d KB at %p\n", + cache_size / 1024, tcode_start)); + g_translation_cache_p -= cache_size; + } + return; + } #endif + D(bug("basic_jit_cache: Release translation cache\n")); vm_release(tcode_start, cache_size); } } diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp index 0b734e78..149d9b8d 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp @@ -28,10 +28,8 @@ class basic_jit_cache { // Default cache size (2 MB) -public: static const uint32 JIT_CACHE_SIZE = 2 * 1024 * 1024; static const uint32 JIT_CACHE_SIZE_GUARD = 4096; -private: uint32 cache_size; // Translation cache (allocated base, current pointer, end pointer) @@ -43,7 +41,7 @@ private: protected: // Initialize translation cache - bool init_translation_cache(uint32 size); + bool init_translation_cache(int size); void kill_translation_cache(); // Initialize user code start @@ -56,8 +54,8 @@ public: public: - // Default constructor & destructor - basic_jit_cache(uint32 init_cache_size = JIT_CACHE_SIZE); + // Default constructor & destructor (use default JIT_CACHE_SIZE) + basic_jit_cache(int init_cache_size = -1); ~basic_jit_cache(); // Invalidate translation cache diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp index 8f64e91c..407ae48c 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp @@ -37,20 +37,6 @@ #endif -/** - * PPC_NO_BASIC_CPU_BASE - * - * Define to not inherit from basic_cpu, thus removing two - * vtables. Otherwise, access to registers require an extra - * offset from "this" because vtables are stored before other - * regular members. - **/ - -#ifndef PPC_NO_BASIC_CPU_BASE -#undef PPC_NO_BASIC_CPU_BASE -#endif - - /** * PPC_NO_STATIC_II_INDEX_TABLE * @@ -144,8 +130,7 @@ * Sanity checks and features enforcements **/ -#ifdef SHEEPSHAVER -#define PPC_NO_BASIC_CPU_BASE +#if KPX_MAX_CPUS == 1 #undef PPC_NO_STATIC_II_INDEX_TABLE #endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp index fb9b302e..19bee244 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp @@ -225,6 +225,7 @@ void powerpc_cpu::initialize() init_decoder(); init_registers(); init_decode_cache(); + execute_depth = 0; // Init cache range invalidate recorder cache_range.start = cache_range.end = 0; @@ -365,14 +366,16 @@ bool powerpc_cpu::check_spcflags() return true; } -void powerpc_cpu::execute(uint32 entry, bool enable_cache) + +void powerpc_cpu::execute(uint32 entry) { pc() = entry; #if PPC_EXECUTE_DUMP_STATE const bool dump_state = true; #endif + execute_depth++; #if PPC_ENABLE_JIT - if (enable_cache) { + if (execute_depth == 1) { for (;;) { block_info *bi = compile_block(pc()); @@ -382,7 +385,7 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) if (!spcflags().empty()) { if (!check_spcflags()) - return; + goto return_site; // Force redecoding if cache was invalidated if (spcflags().test(SPCFLAG_JIT_EXEC_RETURN)) { @@ -395,11 +398,11 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) break; } } - return; + goto return_site; } #endif #if PPC_DECODE_CACHE - if (enable_cache) { + if (execute_depth == 1) { for (;;) { #if PPC_PROFILE_COMPILE_TIME compile_count++; @@ -474,7 +477,7 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) if (!spcflags().empty()) { if (!check_spcflags()) - return; + goto return_site; // Force redecoding if cache was invalidated if (spcflags().test(SPCFLAG_JIT_EXEC_RETURN)) { @@ -487,7 +490,7 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) break; } } - return; + goto return_site; } #endif for (;;) { @@ -508,8 +511,10 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) dump_registers(); #endif if (!spcflags().empty() && !check_spcflags()) - return; + goto return_site; } + return_site: + --execute_depth; } void powerpc_cpu::execute() diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp index 74ed9232..a85e6c59 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp @@ -33,7 +33,7 @@ #include class powerpc_cpu -#ifndef PPC_NO_BASIC_CPU_BASE +#ifndef SHEEPSHAVER : public basic_cpu #endif { @@ -200,10 +200,13 @@ private: // Check special CPU flags bool check_spcflags(); + // Current execute() nested level + int execute_depth; + public: // Initialization & finalization -#ifdef PPC_NO_BASIC_CPU_BASE +#ifdef SHEEPSHAVER powerpc_cpu() #if PPC_ENABLE_JIT : codegen(this) @@ -238,7 +241,7 @@ public: void fake_dump_registers(uint32); // Start emulation loop - void execute(uint32 entry, bool enable_cache = true); + void execute(uint32 entry); void execute(); // Interrupts handling @@ -311,7 +314,6 @@ private: friend class powerpc_dyngen; powerpc_dyngen codegen; block_info *compile_block(uint32 entry); - powerpc_dyngen *codegen_ptr() { return &codegen; } #endif // Semantic action templates diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp index 2f192e14..ef0c6697 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp @@ -73,8 +73,8 @@ public: friend class powerpc_dyngen_helper; // Default constructor - powerpc_dyngen(dyngen_cpu_base cpu) - : basic_dyngen(cpu) + powerpc_dyngen(dyngen_cpu_base cpu, int cache_size = -1) + : basic_dyngen(cpu, cache_size) { } // Load/store registers