nkeynes@378: /** nkeynes@378: * $Id: sh4.c,v 1.1 2007-09-12 09:20:38 nkeynes Exp $ nkeynes@378: * nkeynes@378: * SH4 parent module for all CPU modes and SH4 peripheral nkeynes@378: * modules. nkeynes@378: * nkeynes@378: * Copyright (c) 2005 Nathan Keynes. nkeynes@378: * nkeynes@378: * This program is free software; you can redistribute it and/or modify nkeynes@378: * it under the terms of the GNU General Public License as published by nkeynes@378: * the Free Software Foundation; either version 2 of the License, or nkeynes@378: * (at your option) any later version. nkeynes@378: * nkeynes@378: * This program is distributed in the hope that it will be useful, nkeynes@378: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@378: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@378: * GNU General Public License for more details. nkeynes@378: */ nkeynes@378: nkeynes@378: #define MODULE sh4_module nkeynes@378: #include nkeynes@378: #include "dream.h" nkeynes@378: #include "sh4/sh4core.h" nkeynes@378: #include "sh4/sh4mmio.h" nkeynes@378: #include "sh4/intc.h" nkeynes@378: #include "mem.h" nkeynes@378: #include "clock.h" nkeynes@378: #include "syscall.h" nkeynes@378: nkeynes@378: void sh4_init( void ); nkeynes@378: void sh4_reset( void ); nkeynes@378: void sh4_start( void ); nkeynes@378: void sh4_stop( void ); nkeynes@378: void sh4_save_state( FILE *f ); nkeynes@378: int sh4_load_state( FILE *f ); nkeynes@378: nkeynes@378: uint32_t sh4_run_slice( uint32_t ); nkeynes@378: uint32_t sh4_xlat_run_slice( uint32_t ); nkeynes@378: nkeynes@378: struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_reset, nkeynes@378: NULL, sh4_run_slice, sh4_stop, nkeynes@378: sh4_save_state, sh4_load_state }; nkeynes@378: nkeynes@378: struct sh4_registers sh4r; nkeynes@378: struct breakpoint_struct sh4_breakpoints[MAX_BREAKPOINTS]; nkeynes@378: int sh4_breakpoint_count = 0; nkeynes@378: nkeynes@378: void sh4_set_use_xlat( gboolean use ) nkeynes@378: { nkeynes@378: if( use ) { nkeynes@378: xlat_cache_init(); nkeynes@378: sh4_x86_init(); nkeynes@378: sh4_module.run_time_slice = sh4_xlat_run_slice; nkeynes@378: } else { nkeynes@378: sh4_module.run_time_slice = sh4_run_slice; nkeynes@378: } nkeynes@378: } nkeynes@378: nkeynes@378: void sh4_init(void) nkeynes@378: { nkeynes@378: register_io_regions( mmio_list_sh4mmio ); nkeynes@378: MMU_init(); nkeynes@378: sh4_reset(); nkeynes@378: } nkeynes@378: nkeynes@378: void sh4_reset(void) nkeynes@378: { nkeynes@378: /* zero everything out, for the sake of having a consistent state. */ nkeynes@378: memset( &sh4r, 0, sizeof(sh4r) ); nkeynes@378: nkeynes@378: /* Resume running if we were halted */ nkeynes@378: sh4r.sh4_state = SH4_STATE_RUNNING; nkeynes@378: nkeynes@378: sh4r.pc = 0xA0000000; nkeynes@378: sh4r.new_pc= 0xA0000002; nkeynes@378: sh4r.vbr = 0x00000000; nkeynes@378: sh4r.fpscr = 0x00040001; nkeynes@378: sh4r.sr = 0x700000F0; nkeynes@378: sh4r.fr_bank = &sh4r.fr[0][0]; nkeynes@378: nkeynes@378: /* Mem reset will do this, but if we want to reset _just_ the SH4... */ nkeynes@378: MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET ); nkeynes@378: nkeynes@378: /* Peripheral modules */ nkeynes@378: CPG_reset(); nkeynes@378: INTC_reset(); nkeynes@378: MMU_reset(); nkeynes@378: TMU_reset(); nkeynes@378: SCIF_reset(); nkeynes@378: } nkeynes@378: nkeynes@378: void sh4_stop(void) nkeynes@378: { nkeynes@378: nkeynes@378: } nkeynes@378: nkeynes@378: void sh4_save_state( FILE *f ) nkeynes@378: { nkeynes@378: fwrite( &sh4r, sizeof(sh4r), 1, f ); nkeynes@378: MMU_save_state( f ); nkeynes@378: INTC_save_state( f ); nkeynes@378: TMU_save_state( f ); nkeynes@378: SCIF_save_state( f ); nkeynes@378: } nkeynes@378: nkeynes@378: int sh4_load_state( FILE * f ) nkeynes@378: { nkeynes@378: fread( &sh4r, sizeof(sh4r), 1, f ); nkeynes@378: MMU_load_state( f ); nkeynes@378: INTC_load_state( f ); nkeynes@378: TMU_load_state( f ); nkeynes@378: return SCIF_load_state( f ); nkeynes@378: } nkeynes@378: nkeynes@378: nkeynes@378: void sh4_set_breakpoint( uint32_t pc, int type ) nkeynes@378: { nkeynes@378: sh4_breakpoints[sh4_breakpoint_count].address = pc; nkeynes@378: sh4_breakpoints[sh4_breakpoint_count].type = type; nkeynes@378: sh4_breakpoint_count++; nkeynes@378: } nkeynes@378: nkeynes@378: gboolean sh4_clear_breakpoint( uint32_t pc, int type ) nkeynes@378: { nkeynes@378: int i; nkeynes@378: nkeynes@378: for( i=0; i