| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | /*====================================================================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    filename:     gdsp_interpreter.cpp | 
					
						
							|  |  |  |    project:      GCemu | 
					
						
							|  |  |  |    created:      2004-6-18 | 
					
						
							|  |  |  |    mail:		  duddie@walla.com | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Copyright (c) 2005 Duddie & Tratax | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |    modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |    as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |    of the License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    ====================================================================*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-01 20:22:43 +00:00
										 |  |  | #include "DSPTables.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-12 10:21:40 +00:00
										 |  |  | #include "DSPHost.h"
 | 
					
						
							| 
									
										
										
										
											2009-05-01 20:06:24 +00:00
										 |  |  | #include "DSPCore.h"
 | 
					
						
							|  |  |  | #include "DSPAnalyzer.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-01 20:22:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 11:47:39 +00:00
										 |  |  | #include "DSPHWInterface.h"
 | 
					
						
							| 
									
										
										
										
											2009-06-28 10:00:25 +00:00
										 |  |  | #include "DSPIntUtil.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-01 20:06:24 +00:00
										 |  |  | namespace DSPInterpreter { | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | volatile u32 gdsp_running; | 
					
						
							| 
									
										
										
										
											2009-04-05 09:23:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 10:00:25 +00:00
										 |  |  | // NOTE: These have nothing to do with g_dsp.r[DSP_REG_CR].
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-05 11:55:18 +00:00
										 |  |  | // Hm, should instructions that change CR use this? Probably not (but they
 | 
					
						
							|  |  |  | // should call UpdateCachedCR())
 | 
					
						
							| 
									
										
										
										
											2009-05-01 22:17:22 +00:00
										 |  |  | void WriteCR(u16 val) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	// reset
 | 
					
						
							| 
									
										
										
										
											2010-09-02 01:36:45 +00:00
										 |  |  | 	if (val & 1) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-06-07 11:06:40 +00:00
										 |  |  | 		DSPCore_Reset(); | 
					
						
							| 
									
										
										
										
											2010-09-02 01:36:45 +00:00
										 |  |  | 		val &= ~1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// init - can reset and init be done at the same time?
 | 
					
						
							|  |  |  | 	else if (val == 4) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// this looks like a hack! OSInitAudioSystem ucode
 | 
					
						
							|  |  |  | 		// should send this mail - not dsp core itself
 | 
					
						
							|  |  |  | 		gdsp_mbox_write_h(GDSP_MBOX_DSP, 0x8054); | 
					
						
							|  |  |  | 		gdsp_mbox_write_l(GDSP_MBOX_DSP, 0x4348); | 
					
						
							|  |  |  | 		val |= 0x800; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// update cr
 | 
					
						
							|  |  |  | 	g_dsp.cr = val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-05 11:55:18 +00:00
										 |  |  | // Hm, should instructions that read CR use this? (Probably not).
 | 
					
						
							| 
									
										
										
										
											2009-05-01 22:17:22 +00:00
										 |  |  | u16 ReadCR() | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (g_dsp.pc & 0x8000) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		g_dsp.cr |= 0x800; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		g_dsp.cr &= ~0x800; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-05 11:55:18 +00:00
										 |  |  | 	return g_dsp.cr; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-01 22:17:22 +00:00
										 |  |  | void Step() | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-07 11:06:40 +00:00
										 |  |  | 	DSPCore_CheckExceptions(); | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	g_dsp.step_counter++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-24 02:15:04 +00:00
										 |  |  | #if PROFILE
 | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 	g_dsp.err_pc = g_dsp.pc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ProfilerAddDelta(g_dsp.err_pc, 1); | 
					
						
							|  |  |  | 	if (g_dsp.step_counter == 1) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 		ProfilerInit(); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 	if ((g_dsp.step_counter & 0xFFFFF) == 0) | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 		ProfilerDump(g_dsp.step_counter); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 	u16 opc = dsp_fetch_code(); | 
					
						
							|  |  |  | 	ExecuteInstruction(UDSPInstruction(opc)); | 
					
						
							| 
									
										
										
										
											2010-10-04 12:50:16 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	if (DSPAnalyzer::code_flags[g_dsp.pc - 1] & DSPAnalyzer::CODE_LOOP_END) | 
					
						
							|  |  |  | 		HandleLoop(); | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | // Used by thread mode.
 | 
					
						
							| 
									
										
										
										
											2009-05-01 22:17:22 +00:00
										 |  |  | void Run() | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-18 06:20:52 +00:00
										 |  |  | 	int checkInterrupt = 0; | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	gdsp_running = true; | 
					
						
							| 
									
										
										
										
											2010-03-18 06:20:52 +00:00
										 |  |  | 	while (!(g_dsp.cr & CR_HALT) && gdsp_running) | 
					
						
							| 
									
										
										
										
											2010-04-07 15:04:45 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-05-29 21:34:34 +00:00
										 |  |  | 		if (jit) | 
					
						
							|  |  |  | 			jit->RunForCycles(1); | 
					
						
							| 
									
										
										
										
											2010-04-07 15:04:45 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			// Automatically let the other threads work if we're idle skipping
 | 
					
						
							|  |  |  | 			if(DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) | 
					
						
							|  |  |  | 				Common::YieldCPU(); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			Step(); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			// Turns out the less you check for external interrupts, the more 
 | 
					
						
							|  |  |  | 			// sound you hear, and it becomes slower
 | 
					
						
							|  |  |  | 			checkInterrupt++; | 
					
						
							|  |  |  | 			if(checkInterrupt == 500) { // <-- Arbitrary number. TODO: tweak
 | 
					
						
							|  |  |  | 				DSPCore_CheckExternalInterrupt(); | 
					
						
							|  |  |  | 				checkInterrupt = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-03-18 06:20:52 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	gdsp_running = false; | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | // This one has basic idle skipping, and checks breakpoints.
 | 
					
						
							|  |  |  | int RunCyclesDebug(int cycles) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 	// First, let's run a few cycles with no idle skipping so that things can progress a bit.
 | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | 	for (int i = 0; i < 8; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (g_dsp.cr & CR_HALT) | 
					
						
							|  |  |  | 			return 0;  | 
					
						
							| 
									
										
										
										
											2009-06-28 17:18:52 +00:00
										 |  |  | 		if (dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			DSPCore_SetState(DSPCORE_STEPPING); | 
					
						
							|  |  |  | 			return cycles; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | 		Step(); | 
					
						
							|  |  |  | 		cycles--; | 
					
						
							| 
									
										
										
										
											2009-06-28 17:18:52 +00:00
										 |  |  | 		if (cycles < 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-28 17:18:52 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-03-13 02:28:21 +00:00
										 |  |  | 	DSPCore_CheckExternalInterrupt(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 	while (true) | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 		// Next, let's run a few cycles with idle skipping, so that we can skip
 | 
					
						
							|  |  |  | 		// idle loops.
 | 
					
						
							|  |  |  | 		for (int i = 0; i < 8; i++) | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 			if (g_dsp.cr & CR_HALT) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			if (dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DSPCore_SetState(DSPCORE_STEPPING); | 
					
						
							|  |  |  | 				return cycles; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Idle skipping.
 | 
					
						
							|  |  |  | 			if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			Step(); | 
					
						
							|  |  |  | 			cycles--; | 
					
						
							|  |  |  | 			if (cycles < 0) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-06-28 17:18:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 		// Now, lets run some more without idle skipping. 
 | 
					
						
							|  |  |  | 		for (int i = 0; i < 200; i++) | 
					
						
							| 
									
										
										
										
											2009-06-28 17:18:52 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 			if (dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DSPCore_SetState(DSPCORE_STEPPING); | 
					
						
							|  |  |  | 				return cycles; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Step(); | 
					
						
							|  |  |  | 			cycles--; | 
					
						
							|  |  |  | 			if (cycles < 0) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2010-05-29 21:34:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 			// We don't bother directly supporting pause - if the main emu pauses,
 | 
					
						
							|  |  |  | 			// it just won't call this function anymore.
 | 
					
						
							| 
									
										
										
										
											2009-06-28 17:18:52 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Used by non-thread mode. Meant to be efficient.
 | 
					
						
							|  |  |  | int RunCycles(int cycles) | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-07 15:04:45 +00:00
										 |  |  | 	// First, let's run a few cycles with no idle skipping so that things can
 | 
					
						
							|  |  |  | 	// progress a bit.
 | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | 	for (int i = 0; i < 8; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-05-01 20:06:24 +00:00
										 |  |  | 		if (g_dsp.cr & CR_HALT) | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:40 +00:00
										 |  |  | 			return 0;  | 
					
						
							| 
									
										
										
										
											2009-05-01 22:17:22 +00:00
										 |  |  | 		Step(); | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | 		cycles--; | 
					
						
							| 
									
										
										
										
											2010-03-18 06:20:52 +00:00
										 |  |  | 		if (cycles < 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-13 02:28:21 +00:00
										 |  |  | 	DSPCore_CheckExternalInterrupt(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 	while (true) | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 		// Next, let's run a few cycles with idle skipping, so that we can skip
 | 
					
						
							|  |  |  | 		// idle loops.
 | 
					
						
							|  |  |  | 		for (int i = 0; i < 8; i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (g_dsp.cr & CR_HALT) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			// Idle skipping.
 | 
					
						
							|  |  |  | 			if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			Step(); | 
					
						
							|  |  |  | 			cycles--; | 
					
						
							|  |  |  | 			if (cycles < 0) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-04-09 13:03:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-22 13:46:00 +00:00
										 |  |  | 		// Now, lets run some more without idle skipping. 
 | 
					
						
							|  |  |  | 		for (int i = 0; i < 200; i++)	 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Step(); | 
					
						
							|  |  |  | 			cycles--; | 
					
						
							|  |  |  | 			if (cycles < 0) | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			// We don't bother directly supporting pause - if the main emu pauses,
 | 
					
						
							|  |  |  | 			// it just won't call this function anymore.
 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-04-08 20:26:33 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-01 22:17:22 +00:00
										 |  |  | void Stop() | 
					
						
							| 
									
										
										
										
											2009-03-23 09:10:32 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	gdsp_running = false; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-01 20:06:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-03 11:15:17 +00:00
										 |  |  | }  // namespace
 |