From 36ce9c07e65a3f42e74f8b27f845219438a6db83 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Thu, 27 Nov 2003 00:26:35 +0000 Subject: [PATCH] Statically allocate the translation cache on PowerPC. This makes it possible to generate direct bl instructions for function invokation. --- SheepShaver/src/Unix/configure.in | 28 +++++++++++++++++++ .../src/kpx_cpu/src/cpu/jit/jit-cache.cpp | 28 +++++++++++++++++-- .../src/kpx_cpu/src/cpu/jit/jit-cache.hpp | 2 ++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/SheepShaver/src/Unix/configure.in b/SheepShaver/src/Unix/configure.in index 3242af42..75f80d1e 100644 --- a/SheepShaver/src/Unix/configure.in +++ b/SheepShaver/src/Unix/configure.in @@ -606,6 +606,34 @@ if [[ "x$EMULATED_PPC" = "xyes" ]]; then fi CPUSRCS="$CPUSRCS ../kpx_cpu/sheepshaver_glue.cpp" fi +if [[ "x$ac_cv_use_dyngen" = "xyes" ]]; then + AC_CACHE_CHECK([whether static data regions are executable], + ac_cv_have_static_data_exec, [ + AC_TRY_RUN([int main(void) { +#if defined(__powerpc__) + static unsigned int p[8] = {0x4e800020,}; + asm volatile("dcbst 0,%0" : : "r" (p) : "memory"); + asm volatile("sync" : : : "memory"); + asm volatile("icbi 0,%0" : : "r" (p) : "memory"); + asm volatile("sync" : : : "memory"); + asm volatile("isync" : : : "memory"); + ((void (*)(void))p)(); + return 0; +#endif +#if defined(__i386__) + static unsigned char p[] = {0xc3}; + ((void (*)(void))p)(); + return 0; +#endif + return 1; + }], ac_cv_have_static_data_exec=yes, ac_cv_have_static_data_exec=no, + dnl When cross-compiling, do not assume anything. + ac_cv_have_static_data_exec=no + ) + ]) +fi +AC_TRANSLATE_DEFINE(HAVE_STATIC_DATA_EXEC, "$ac_cv_have_static_data_exec", + [Define if your system marks static data pages as executable.]) dnl Generate Makefile. AC_SUBST(DYNGENSRCS) 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 3c57d3b9..4ac223e0 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp @@ -25,6 +25,16 @@ #define DEBUG 0 #include "debug.h" +// FIXME: Define this only for SheepShaver. Kheperix will need +// something like KPX_MAX_CPUS == 1. +#ifndef SHEEPSHAVER +#undef HAVE_STATIC_DATA_EXEC +#endif + +#if HAVE_STATIC_DATA_EXEC +static uint8 g_translation_cache[basic_jit_cache::JIT_CACHE_SIZE]; +#endif + basic_jit_cache::basic_jit_cache(uint32 init_cache_size) : tcode_start(NULL), code_start(NULL), code_p(NULL), code_end(NULL) { @@ -41,8 +51,15 @@ basic_jit_cache::init_translation_cache(uint32 size) { // Round up translation cache size to next 16 KB boundaries const uint32 roundup = 16 * 1024; - cache_size = (size + JIT_CACHE_SIZE_GUARD + roundup - 1) & -roundup; + uint32 effective_cache_size = (size - JIT_CACHE_SIZE_GUARD) & -roundup; + cache_size = size & -roundup; +#if HAVE_STATIC_DATA_EXEC + if (cache_size <= JIT_CACHE_SIZE) { + tcode_start = g_translation_cache; + goto done; + } +#endif tcode_start = (uint8 *)vm_acquire(cache_size, VM_MAP_PRIVATE | VM_MAP_32BIT); if (tcode_start == VM_MAP_FAILED) { tcode_start = NULL; @@ -56,16 +73,21 @@ basic_jit_cache::init_translation_cache(uint32 size) return false; } + done: 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 + cache_size; + code_end = code_p + effective_cache_size; return true; } void basic_jit_cache::kill_translation_cache() { - if (tcode_start) + if (tcode_start) { +#if HAVE_STATIC_DATA_EXEC + if (cache_size > JIT_CACHE_SIZE) +#endif 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 92830214..0b734e78 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp @@ -28,8 +28,10 @@ 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)