diff --git a/SheepShaver/src/Unix/configure.in b/SheepShaver/src/Unix/configure.in index cbd2f674..affec936 100644 --- a/SheepShaver/src/Unix/configure.in +++ b/SheepShaver/src/Unix/configure.in @@ -583,7 +583,7 @@ if [[ "x$EMULATED_PPC" = "xyes" ]]; then fi ;; esac - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -finline-limit=2000" + DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -finline-limit=10000" if [[ "x$HAVE_GCC30" = "xyes" ]]; then DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -fno-reorder-blocks -fno-optimize-sibling-calls" fi @@ -627,6 +627,10 @@ fi AC_TRANSLATE_DEFINE(HAVE_STATIC_DATA_EXEC, "$ac_cv_have_static_data_exec", [Define if your system marks static data pages as executable.]) +if [[ "x$WANT_JIT" = "xyes" ]]; then + CPPFLAGS="$CPPFLAGS -DUSE_JIT" +fi + dnl Generate Makefile. AC_SUBST(DYNGENSRCS) AC_SUBST(DYNGEN_OP_FLAGS) diff --git a/SheepShaver/src/Unix/prefs_editor_gtk.cpp b/SheepShaver/src/Unix/prefs_editor_gtk.cpp index ad92ee88..55da4ff7 100644 --- a/SheepShaver/src/Unix/prefs_editor_gtk.cpp +++ b/SheepShaver/src/Unix/prefs_editor_gtk.cpp @@ -47,6 +47,7 @@ static void create_graphics_pane(GtkWidget *top); static void create_input_pane(GtkWidget *top); static void create_serial_pane(GtkWidget *top); static void create_memory_pane(GtkWidget *top); +static void create_jit_pane(GtkWidget *top); static void read_settings(void); @@ -322,6 +323,7 @@ bool PrefsEditor(void) create_input_pane(notebook); create_serial_pane(notebook); create_memory_pane(notebook); + create_jit_pane(notebook); static const opt_desc buttons[] = { {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)}, @@ -498,6 +500,46 @@ static void create_volumes_pane(GtkWidget *top) } +/* + * "JIT Compiler" pane + */ + +// Set sensitivity of widgets +static void set_jit_sensitive(void) +{ + const bool jit_enabled = PrefsFindBool("jit"); +} + +// "Use JIT Compiler" button toggled +static void tb_jit(GtkWidget *widget) +{ + PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active); + set_jit_sensitive(); +} + +// Read settings from widgets and set preferences +static void read_jit_settings(void) +{ +#if USE_JIT + bool jit_enabled = PrefsFindBool("jit"); +#endif +} + +// Create "JIT Compiler" pane +static void create_jit_pane(GtkWidget *top) +{ +#if USE_JIT + GtkWidget *box, *table, *label, *menu; + char str[32]; + + box = make_pane(top, STR_JIT_PANE_TITLE); + make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit)); + + set_jit_sensitive(); +#endif +} + + /* * "Graphics/Sound" pane */ @@ -907,4 +949,5 @@ static void read_settings(void) read_graphics_settings(); read_serial_settings(); read_memory_settings(); + read_jit_settings(); } diff --git a/SheepShaver/src/include/user_strings.h b/SheepShaver/src/include/user_strings.h index f5fbdd9d..66e8dac4 100644 --- a/SheepShaver/src/include/user_strings.h +++ b/SheepShaver/src/include/user_strings.h @@ -130,6 +130,10 @@ enum { STR_IDLEWAIT_CTRL, STR_ROM_FILE_CTRL, + // JIT Compiler pane + STR_JIT_PANE_TITLE = 3700, + STR_JIT_CTRL, + // Mac window STR_WINDOW_TITLE = 4000, STR_WINDOW_TITLE_FROZEN, diff --git a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp index a7e86d68..0e4c5592 100644 --- a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp +++ b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp @@ -93,6 +93,12 @@ static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE; // SIGSEGV handler static sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t); +// JIT Compiler enabled? +static inline bool enable_jit_p() +{ + return PrefsFindBool("jit"); +} + /** * PowerPC emulator glue with special 'sheep' opcodes @@ -150,7 +156,7 @@ public: lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator; sheepshaver_cpu::sheepshaver_cpu() - : powerpc_cpu() + : powerpc_cpu(enable_jit_p()) { init_decoder(); } diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp index 96188ce0..9a4bcfa3 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp @@ -42,8 +42,8 @@ struct powerpc_block_info #endif #if PPC_ENABLE_JIT uint8 * entry_point; - uintptr min_pc, max_pc; #endif + uintptr min_pc, max_pc; bool intersect(uintptr start, uintptr end); }; 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 bd186e2a..90928bc9 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp @@ -145,8 +145,4 @@ #undef PPC_NO_STATIC_II_INDEX_TABLE #endif -#if PPC_ENABLE_JIT -#undef PPC_DECODE_CACHE -#endif - #endif /* PPC_CONFIG_H */ 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 61e98d1e..5fe84337 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp @@ -243,6 +243,11 @@ void powerpc_cpu::initialize() init_decode_cache(); execute_depth = 0; + // Initialize block lookup table +#if PPC_DECODE_CACHE || PPC_ENABLE_JIT + block_cache.initialize(); +#endif + // Init cache range invalidate recorder cache_range.start = cache_range.end = 0; @@ -278,18 +283,22 @@ void powerpc_cpu::initialize() } #ifdef SHEEPSHAVER -powerpc_cpu::powerpc_cpu() +powerpc_cpu::powerpc_cpu(bool do_use_jit) + : use_jit(do_use_jit) #if PPC_ENABLE_JIT - : codegen(this) + , codegen(this) #endif #else powerpc_cpu::powerpc_cpu(task_struct *parent_task) - : basic_cpu(parent_task) + : basic_cpu(parent_task), use_jit(true) #if PPC_ENABLE_JIT - , codegen(this) + , codegen(this) #endif #endif { +#if !PPC_ENABLE_JIT + use_jit = false; +#endif ++ppc_refcount; initialize(); } @@ -302,7 +311,8 @@ powerpc_cpu::~powerpc_cpu() const char *type = NULL; #if PPC_ENABLE_JIT - type = "compile"; + if (use_jit) + type = "compile"; #endif #if PPC_DECODE_CACHE type = "predecode"; @@ -428,35 +438,36 @@ void powerpc_cpu::execute(uint32 entry) const bool dump_state = true; #endif execute_depth++; -#if PPC_ENABLE_JIT +#if PPC_DECODE_CACHE || PPC_ENABLE_JIT if (execute_depth == 1) { - for (;;) { - block_info *bi = compile_block(pc()); - - // Execute all cached blocks +#if PPC_ENABLE_JIT + if (use_jit) { for (;;) { - codegen.execute(bi->entry_point); + block_info *bi = compile_block(pc()); - if (!spcflags().empty()) { - if (!check_spcflags()) - goto return_site; + // Execute all cached blocks + for (;;) { + codegen.execute(bi->entry_point); - // Force redecoding if cache was invalidated - if (spcflags().test(SPCFLAG_JIT_EXEC_RETURN)) { - spcflags().clear(SPCFLAG_JIT_EXEC_RETURN); - break; + if (!spcflags().empty()) { + if (!check_spcflags()) + goto return_site; + + // Force redecoding if cache was invalidated + if (spcflags().test(SPCFLAG_JIT_EXEC_RETURN)) { + spcflags().clear(SPCFLAG_JIT_EXEC_RETURN); + break; + } } - } - if ((bi->pc != pc()) && ((bi = block_cache.find(pc())) == NULL)) - break; + if ((bi->pc != pc()) && ((bi = block_cache.find(pc())) == NULL)) + break; + } } + goto return_site; } - goto return_site; - } #endif #if PPC_DECODE_CACHE - if (execute_depth == 1) { for (;;) { #if PPC_PROFILE_COMPILE_TIME compile_count++; @@ -506,6 +517,8 @@ void powerpc_cpu::execute(uint32 entry) } } while ((ii->cflow & CFLOW_END_BLOCK) == 0); bi->end_pc = dpc; + bi->min_pc = dpc; + bi->max_pc = entry; bi->size = di - bi->di; block_cache.add_to_cl_list(bi); block_cache.add_to_active_list(bi); @@ -544,6 +557,7 @@ void powerpc_cpu::execute(uint32 entry) break; } } +#endif goto return_site; } #endif @@ -597,10 +611,6 @@ void powerpc_cpu::init_decode_cache() decode_cache_end_p -= 2; #endif #endif - -#if PPC_DECODE_CACHE || PPC_ENABLE_JIT - block_cache.initialize(); -#endif } void powerpc_cpu::kill_decode_cache() 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 146a11a8..37634556 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp @@ -212,12 +212,15 @@ private: // Current execute() nested level int execute_depth; + // Do we enable the JIT compiler? + bool use_jit; + public: // Initialization & finalization void initialize(); #ifdef SHEEPSHAVER - powerpc_cpu(); + powerpc_cpu(bool do_use_jit = true); #else powerpc_cpu(task_struct *parent_task); #endif @@ -299,15 +302,18 @@ private: return &ii_table[ii_index_table[get_ii_index(opcode)]]; } - // Decode Cache + // Block lookup table typedef powerpc_block_info block_info; block_cache< block_info, lazy_allocator > block_cache; +#if PPC_DECODE_CACHE + // Decode Cache static const uint32 DECODE_CACHE_MAX_ENTRIES = 32768; static const uint32 DECODE_CACHE_SIZE = DECODE_CACHE_MAX_ENTRIES * sizeof(block_info::decode_info); block_info::decode_info * decode_cache; block_info::decode_info * decode_cache_p; block_info::decode_info * decode_cache_end_p; +#endif #if PPC_ENABLE_JIT // Dynamic translation engine diff --git a/SheepShaver/src/prefs_items.cpp b/SheepShaver/src/prefs_items.cpp index f732de5c..d823d43b 100644 --- a/SheepShaver/src/prefs_items.cpp +++ b/SheepShaver/src/prefs_items.cpp @@ -52,6 +52,7 @@ prefs_desc common_prefs_items[] = { {"nosound", TYPE_BOOLEAN, false, "don't enable sound output"}, {"nogui", TYPE_BOOLEAN, false, "disable GUI"}, {"ignoresegv", TYPE_BOOLEAN, false, "ignore illegal memory accesses"}, + {"jit", TYPE_BOOLEAN, false, "enable JIT compiler"}, {NULL, TYPE_END, false, NULL} // End of list }; @@ -72,4 +73,11 @@ void AddPrefsDefaults(void) PrefsAddBool("nosound", false); PrefsAddBool("nogui", false); PrefsAddBool("ignoresegv", true); + +#if USE_JIT + // JIT compiler specific options + PrefsAddBool("jit", true); +#else + PrefsAddBool("jit", false); +#endif } diff --git a/SheepShaver/src/user_strings.cpp b/SheepShaver/src/user_strings.cpp index 48444dbe..05a138ee 100644 --- a/SheepShaver/src/user_strings.cpp +++ b/SheepShaver/src/user_strings.cpp @@ -138,6 +138,9 @@ user_string_def common_strings[] = { {STR_IDLEWAIT_CTRL, "Don't Use CPU When Idle"}, {STR_ROM_FILE_CTRL, "ROM File"}, + {STR_JIT_PANE_TITLE, "JIT Compiler"}, + {STR_JIT_CTRL, "Enable JIT Compiler"}, + {STR_WINDOW_TITLE, "SheepShaver"}, {STR_WINDOW_TITLE_FROZEN, "SheepShaver *** FROZEN ***"}, {STR_WINDOW_MENU, "SheepShaver"},