nkeynes@359: /** nkeynes@368: * $Id: sh4trans.c,v 1.2 2007-09-04 08:40:23 nkeynes Exp $ nkeynes@359: * nkeynes@359: * SH4 translation core module. This part handles the non-target-specific nkeynes@359: * section of the translation. 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@359: #include "sh4core.h" nkeynes@359: #include "sh4trans.h" nkeynes@359: #include "xltcache.h" nkeynes@359: nkeynes@359: /** nkeynes@359: * Execute a timeslice using translated code only (ie translate/execute loop) nkeynes@359: * Note this version does not support breakpoints nkeynes@359: */ nkeynes@359: uint32_t sh4_xlat_run_slice( uint32_t nanosecs ) nkeynes@359: { nkeynes@368: int i; nkeynes@359: sh4r.slice_cycle = 0; nkeynes@359: nkeynes@359: if( sh4r.sh4_state != SH4_STATE_RUNNING ) { nkeynes@359: if( sh4r.event_pending < nanosecs ) { nkeynes@359: sh4r.sh4_state = SH4_STATE_RUNNING; nkeynes@359: sh4r.slice_cycle = sh4r.event_pending; nkeynes@359: } nkeynes@359: } nkeynes@359: nkeynes@368: while( sh4r.slice_cycle < nanosecs ) { nkeynes@359: if( SH4_EVENT_PENDING() ) { nkeynes@359: if( sh4r.event_types & PENDING_EVENT ) { nkeynes@359: event_execute(); nkeynes@359: } nkeynes@359: /* Eventq execute may (quite likely) deliver an immediate IRQ */ nkeynes@359: if( sh4r.event_types & PENDING_IRQ ) { nkeynes@359: sh4_accept_interrupt(); nkeynes@359: } nkeynes@359: } nkeynes@359: nkeynes@368: gboolean (*code)() = xlat_get_code(sh4r.pc); nkeynes@359: if( code == NULL ) { nkeynes@359: code = sh4_translate_basic_block( sh4r.pc ); nkeynes@359: } nkeynes@368: if( !code() ) nkeynes@368: break; nkeynes@359: } nkeynes@359: nkeynes@359: /* If we aborted early, but the cpu is still technically running, nkeynes@359: * we're doing a hard abort - cut the timeslice back to what we nkeynes@359: * actually executed nkeynes@359: */ nkeynes@359: if( sh4r.slice_cycle < nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) { nkeynes@359: nanosecs = sh4r.slice_cycle; nkeynes@359: } nkeynes@359: if( sh4r.sh4_state != SH4_STATE_STANDBY ) { nkeynes@359: TMU_run_slice( nanosecs ); nkeynes@359: SCIF_run_slice( nanosecs ); nkeynes@359: } nkeynes@359: return nanosecs; nkeynes@359: } nkeynes@359: nkeynes@359: uint8_t *xlat_output; nkeynes@359: nkeynes@359: /** nkeynes@359: * Translate a linear basic block, ie all instructions from the start address nkeynes@359: * (inclusive) until the next branch/jump instruction or the end of the page nkeynes@359: * is reached. nkeynes@359: * @return the address of the translated block nkeynes@359: * eg due to lack of buffer space. nkeynes@359: */ nkeynes@359: void * sh4_translate_basic_block( sh4addr_t start ) nkeynes@359: { nkeynes@359: uint32_t pc = start; nkeynes@359: int done; nkeynes@359: xlat_cache_block_t block = xlat_start_block( start ); nkeynes@359: xlat_output = (uint8_t *)block->code; nkeynes@359: uint8_t *eob = xlat_output + block->size; nkeynes@359: sh4_translate_begin_block(); nkeynes@359: nkeynes@359: while( (done = sh4_x86_translate_instruction( pc )) == 0 ) { nkeynes@359: if( eob - xlat_output < MAX_INSTRUCTION_SIZE ) { nkeynes@359: uint8_t *oldstart = block->code; nkeynes@359: block = xlat_extend_block(); nkeynes@359: xlat_output = block->code + (xlat_output - oldstart); nkeynes@359: eob = block->code + block->size; nkeynes@359: } nkeynes@359: pc += 2; nkeynes@359: } nkeynes@368: sh4_translate_end_block(pc); nkeynes@368: xlat_commit_block( xlat_output - block->code, pc-start ); nkeynes@359: return block->code; nkeynes@359: } nkeynes@359: nkeynes@359: