nkeynes@359: /** nkeynes@586: * $Id$ nkeynes@359: * nkeynes@359: * SH4->x86 translation module nkeynes@359: * nkeynes@359: * Copyright (c) 2005 Nathan Keynes. nkeynes@359: * nkeynes@359: * This program is free software; you can redistribute it and/or modify nkeynes@359: * it under the terms of the GNU General Public License as published by nkeynes@359: * the Free Software Foundation; either version 2 of the License, or nkeynes@359: * (at your option) any later version. nkeynes@359: * nkeynes@359: * This program is distributed in the hope that it will be useful, nkeynes@359: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@359: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@359: * GNU General Public License for more details. nkeynes@359: */ nkeynes@359: nkeynes@586: #include "sh4/xltcache.h" nkeynes@359: #include "dream.h" nkeynes@359: #include "mem.h" nkeynes@359: nkeynes@707: /** Maximum size of a translated instruction, in bytes. Current worst case seems nkeynes@707: * to be a BF/S followed by one of the long FMOVs. nkeynes@359: */ nkeynes@707: #define MAX_INSTRUCTION_SIZE 384 nkeynes@410: /** Maximum size of the translation epilogue (current real size is 116 bytes, so nkeynes@410: * allows a little room nkeynes@410: */ nkeynes@410: #define EPILOGUE_SIZE 128 nkeynes@586: nkeynes@586: /** Maximum number of recovery records for a translated block (2048 based on nkeynes@586: * 1 record per SH4 instruction in a 4K page). nkeynes@586: */ nkeynes@733: #define MAX_RECOVERY_SIZE 2049 nkeynes@586: nkeynes@359: /** nkeynes@586: * Translation flag - exit the current block but continue (eg exception handling) nkeynes@586: */ nkeynes@586: #define XLAT_EXIT_CONTINUE 1 nkeynes@359: nkeynes@586: /** nkeynes@586: * Translation flag - exit the current block and halt immediately (eg fatal error) nkeynes@586: */ nkeynes@586: #define XLAT_EXIT_HALT 2 nkeynes@586: nkeynes@586: /** nkeynes@586: * Translation flag - exit the current block and halt immediately for a system nkeynes@586: * breakpoint. nkeynes@586: */ nkeynes@586: #define XLAT_EXIT_BREAKPOINT 3 nkeynes@586: nkeynes@586: /** nkeynes@586: * Translation flag - exit the current block and continue after performing a full nkeynes@586: * system reset (dreamcast_reset()) nkeynes@586: */ nkeynes@586: #define XLAT_EXIT_SYSRESET 4 nkeynes@586: nkeynes@586: /** nkeynes@617: * Translation flag - exit the current block and continue after the next IRQ. nkeynes@617: */ nkeynes@617: #define XLAT_EXIT_SLEEP 5 nkeynes@617: nkeynes@617: /** nkeynes@359: */ nkeynes@359: uint32_t sh4_xlat_run_slice( uint32_t nanosecs ); nkeynes@359: nkeynes@359: /** nkeynes@586: * Return true if translated code is currently running nkeynes@586: */ nkeynes@586: gboolean sh4_xlat_is_running(); nkeynes@586: nkeynes@586: /** nkeynes@669: * Initialize the translation engine (if required). Note xlat cache nkeynes@669: * must already be initialized. nkeynes@669: */ nkeynes@669: void sh4_xlat_init(); nkeynes@669: nkeynes@669: /** nkeynes@359: * Translate the specified block of code starting from the specified start nkeynes@359: * address until the first branch/jump instruction. nkeynes@359: */ nkeynes@359: void *sh4_translate_basic_block( sh4addr_t start ); nkeynes@359: nkeynes@669: /** nkeynes@669: * Add a recovery record for the current code generation position, with the nkeynes@669: * specified instruction count nkeynes@669: */ nkeynes@669: void sh4_translate_add_recovery( uint32_t icount ); nkeynes@586: nkeynes@359: extern uint8_t *xlat_output; nkeynes@586: extern struct xlat_recovery_record xlat_recovery[MAX_RECOVERY_SIZE]; nkeynes@604: extern xlat_cache_block_t xlat_current_block; nkeynes@586: extern uint32_t xlat_recovery_posn; nkeynes@359: nkeynes@526: /****************************************************************************** nkeynes@526: * Code generation - these methods must be provided by the nkeynes@526: * actual code gen (eg sh4x86.c) nkeynes@526: ******************************************************************************/ nkeynes@359: nkeynes@527: #define TARGET_X86 1 nkeynes@527: nkeynes@669: void sh4_translate_init( void ); nkeynes@408: void sh4_translate_begin_block( sh4addr_t pc ); nkeynes@526: uint32_t sh4_translate_instruction( sh4addr_t pc ); nkeynes@359: void sh4_translate_end_block( sh4addr_t pc ); nkeynes@593: uint32_t sh4_translate_end_block_size(); nkeynes@669: void sh4_translate_emit_breakpoint( sh4vma_t pc ); nkeynes@586: nkeynes@586: typedef void (*unwind_thunk_t)(void); nkeynes@586: nkeynes@586: /** nkeynes@586: * From within the translator, (typically called from MMU exception handling routines) nkeynes@586: * immediately exit the current translation block (performing cleanup as necessary) and nkeynes@586: * return to sh4_xlat_run_slice(). Effectively a fast longjmp w/ xlat recovery. nkeynes@586: * nkeynes@586: * Note: The correct working of this method depends on the translator anticipating the nkeynes@586: * exception and generating the appropriate recovery block(s) - currently this means nkeynes@586: * that it should ONLY be called from within the context of a memory read or write. nkeynes@586: * nkeynes@586: * @param is_completion If TRUE, exit after completing the current instruction (effectively), nkeynes@586: * otherwise abort the current instruction with no effect. nkeynes@586: * @param thunk A function to execute after perform xlat recovery, but before returning nkeynes@586: * to run_slice. If NULL, control returns directly. nkeynes@586: * @return This method never returns. nkeynes@586: */ nkeynes@586: void sh4_translate_unwind_stack( gboolean is_completion, unwind_thunk_t thunk ); nkeynes@586: nkeynes@586: /** nkeynes@586: * From within the translator, immediately exit the current translation block with nkeynes@586: * the specified exit code (one of the XLAT_EXIT_* values). nkeynes@586: */ nkeynes@586: void sh4_translate_exit( int exit_code ); nkeynes@591: nkeynes@591: /** nkeynes@669: * From within the translator, exit the current block at the end of the nkeynes@669: * current instruction, flush the translation cache (completely) and return nkeynes@669: * control to sh4_xlat_run_slice. nkeynes@669: */ nkeynes@669: void sh4_translate_flush_cache( void ); nkeynes@669: nkeynes@669: /** nkeynes@591: * Support function called from the translator when a breakpoint is hit. nkeynes@591: * Either returns immediately (to skip the breakpoint), or aborts the current nkeynes@591: * cycle and never returns. nkeynes@591: */ nkeynes@591: void sh4_translate_breakpoint_hit( sh4vma_t pc );