summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpuexec.c
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2008-01-29 23:27:24 +0000
committer Aaron Giles <aaron@aarongiles.com>2008-01-29 23:27:24 +0000
commit19dc5dba41f3fe07f66f16ed250b903f120e41da (patch)
tree03a6ef9302be6f36299dbde310211ca51ca04877 /src/emu/cpuexec.c
parentef7452b85255316e7ff7919eb8077b9559f76e94 (diff)
Moved cpu_getiloops() and cpu_scalebyfcount() to deprecat.h.
Added #include "deprecat.h" where necessary to make this happen. Cleaned up cpuexec.c/.h to latest core style. Cleaned up implementation of extended INP header in inptport.c. Removed external access to cycles_currently_ran(). Replaced use of cycles_currently_ran() in v9938 code with mame_rand(), since that is effectively the same thing. :)
Diffstat (limited to 'src/emu/cpuexec.c')
-rw-r--r--src/emu/cpuexec.c1015
1 files changed, 414 insertions, 601 deletions
diff --git a/src/emu/cpuexec.c b/src/emu/cpuexec.c
index c7b2ae04cbf..725edd3a613 100644
--- a/src/emu/cpuexec.c
+++ b/src/emu/cpuexec.c
@@ -21,11 +21,9 @@
-/*************************************
- *
- * Debug logging
- *
- *************************************/
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
#define VERBOSE 0
@@ -33,11 +31,9 @@
-/*************************************
- *
- * Macros to help verify active CPU
- *
- *************************************/
+/***************************************************************************
+ MACROS
+***************************************************************************/
#define VERIFY_ACTIVECPU(name) \
int activecpu = cpu_getactivecpu(); \
@@ -52,12 +48,11 @@
-/*************************************
- *
- * Triggers for the timer system
- *
- *************************************/
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+/* internal trigger IDs */
enum
{
TRIGGER_TIMESLICE = -1000,
@@ -68,63 +63,54 @@ enum
-/*************************************
- *
- * Internal CPU info structure
- *
- *************************************/
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+/* Internal CPU info structure */
typedef struct _cpuexec_data cpuexec_data;
struct _cpuexec_data
{
- UINT8 saveable; /* true if saveable */
+ UINT8 saveable; /* true if saveable */
- UINT8 suspend; /* suspend reason mask (0 = not suspended) */
- UINT8 nextsuspend; /* pending suspend reason mask */
- UINT8 eatcycles; /* true if we eat cycles while suspended */
- UINT8 nexteatcycles; /* pending value */
- INT32 trigger; /* pending trigger to release a trigger suspension */
+ UINT8 suspend; /* suspend reason mask (0 = not suspended) */
+ UINT8 nextsuspend; /* pending suspend reason mask */
+ UINT8 eatcycles; /* true if we eat cycles while suspended */
+ UINT8 nexteatcycles; /* pending value */
+ INT32 trigger; /* pending trigger to release a trigger suspension */
- INT32 iloops; /* number of interrupts remaining this frame */
+ INT32 iloops; /* number of interrupts remaining this frame */
- UINT64 totalcycles; /* total CPU cycles executed */
- attotime localtime; /* local time, relative to the timer system's global time */
- INT32 clock; /* current active clock */
- double clockscale; /* current active clock scale factor */
+ UINT64 totalcycles; /* total CPU cycles executed */
+ attotime localtime; /* local time, relative to the timer system's global time */
+ INT32 clock; /* current active clock */
+ double clockscale; /* current active clock scale factor */
- INT32 vblankint_countdown; /* number of vblank callbacks left until we interrupt */
- INT32 vblankint_multiplier; /* number of vblank callbacks per interrupt */
- void * vblankint_timer; /* reference to elapsed time counter */
+ INT32 vblankint_countdown; /* number of vblank callbacks left until we interrupt */
+ INT32 vblankint_multiplier; /* number of vblank callbacks per interrupt */
+ emu_timer * vblankint_timer; /* reference to elapsed time counter */
- void * timedint_timer; /* reference to this CPU's timer */
- attotime timedint_period; /* timing period of the timed interrupt */
+ emu_timer * timedint_timer; /* reference to this CPU's timer */
+ attotime timedint_period; /* timing period of the timed interrupt */
};
-/*************************************
- *
- * General CPU variables
- *
- *************************************/
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+/* general CPU variables */
static cpuexec_data cpu[MAX_CPU];
static UINT8 vblank;
static UINT32 current_frame;
-static INT32 watchdog_counter;
static int cycles_running;
static int cycles_stolen;
-
-/*************************************
- *
- * Timer variables
- *
- *************************************/
-
+/* timer variables */
static emu_timer *vblank_timer;
static INT32 vblank_countdown;
static INT32 vblank_multiplier;
@@ -142,15 +128,16 @@ static emu_timer *interleave_boost_timer;
static emu_timer *interleave_boost_timer_end;
static attotime perfect_interleave;
+/* watchdog state */
+static UINT8 watchdog_enabled;
+static INT32 watchdog_counter;
static emu_timer *watchdog_timer;
-/*************************************
- *
- * Static prototypes
- *
- *************************************/
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
static void cpuexec_exit(running_machine *machine);
static void cpuexec_reset(running_machine *machine);
@@ -160,33 +147,19 @@ static TIMER_CALLBACK( cpu_vblankcallback );
static TIMER_CALLBACK( cpu_updatecallback );
static TIMER_CALLBACK( end_interleave_boost );
static void compute_perfect_interleave(running_machine *machine);
-static void watchdog_setup(running_machine *machine, int alloc_new);
-
-
-/*************************************
- *
- * Watchdog Flags
- *
- *************************************/
+void cpu_compute_vblank_timing(running_machine *machine);
-#define WATCHDOG_IS_STARTED_DISABLED -1
-#define WATCHDOG_IS_DISABLED -2
-#define WATCHDOG_IS_TIMER_BASED -3
-#define WATCHDOG_IS_INVALID -4
-#define WATCHDOG_IS_BEING_STARTED -5
+/***************************************************************************
+ CORE CPU EXECUTION
+***************************************************************************/
-#if 0
-#pragma mark CORE CPU
-#endif
-
-/*************************************
- *
- * Initialize all the CPUs
- *
- *************************************/
+/*-------------------------------------------------
+ cpuexec_init - initialize internal states of
+ all CPUs
+-------------------------------------------------*/
void cpuexec_init(running_machine *machine)
{
@@ -266,18 +239,17 @@ void cpuexec_init(running_machine *machine)
state_save_push_tag(0);
state_save_register_item("cpu", 0, vblank);
state_save_register_item("cpu", 0, current_frame);
+ state_save_register_item("cpu", 0, watchdog_enabled);
state_save_register_item("cpu", 0, watchdog_counter);
state_save_register_item("cpu", 0, vblank_countdown);
state_save_pop_tag();
}
-
-/*************************************
- *
- * Prepare the system for execution
- *
- *************************************/
+/*-------------------------------------------------
+ cpuexec_reset - reset CPU states on a soft
+ reset
+-------------------------------------------------*/
static void cpuexec_reset(running_machine *machine)
{
@@ -285,8 +257,10 @@ static void cpuexec_reset(running_machine *machine)
/* initialize the various timers (suspends all CPUs at startup) */
cpu_inittimers(machine);
- watchdog_counter = WATCHDOG_IS_INVALID;
- watchdog_setup(machine, TRUE);
+
+ /* set up the watchdog timer; only start off enabled if explicitly configured */
+ watchdog_enabled = (machine->drv->watchdog_vblank_count != 0 || attotime_compare(machine->drv->watchdog_time, attotime_zero) != 0);
+ watchdog_reset(machine);
/* first pass over CPUs */
for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
@@ -311,12 +285,9 @@ static void cpuexec_reset(running_machine *machine)
}
-
-/*************************************
- *
- * Deinitialize all the CPUs
- *
- *************************************/
+/*-------------------------------------------------
+ cpuexec_exit - cleanup all CPUs on exit
+-------------------------------------------------*/
static void cpuexec_exit(running_machine *machine)
{
@@ -328,137 +299,10 @@ static void cpuexec_exit(running_machine *machine)
}
-
-
-#if 0
-#pragma mark -
-#pragma mark WATCHDOG
-#endif
-
-/*************************************
- *
- * Watchdog timer callback
- *
- *************************************/
-
-static TIMER_CALLBACK( watchdog_callback )
-{
- logerror("reset caused by the (time) watchdog\n");
- mame_schedule_soft_reset(machine);
-}
-
-
-
-/*************************************
- *
- * Watchdog setup routine
- *
- *************************************/
-
-static void watchdog_setup(running_machine *machine, int alloc_new)
-{
- if (watchdog_counter != WATCHDOG_IS_DISABLED)
- {
- if (machine->drv->watchdog_vblank_count)
- {
- /* Start a vblank based watchdog. */
- watchdog_counter = machine->drv->watchdog_vblank_count;
- }
- else if (attotime_compare(machine->drv->watchdog_time, attotime_zero) != 0)
- {
- /* Start a time based watchdog. */
- if (alloc_new)
- watchdog_timer = timer_alloc(watchdog_callback, NULL);
- timer_adjust(watchdog_timer, machine->drv->watchdog_time, 0, attotime_zero);
- watchdog_counter = WATCHDOG_IS_TIMER_BASED;
- }
- else if (watchdog_counter == WATCHDOG_IS_INVALID)
- {
- /* The watchdog was not initialized in the MACHINE_DRIVER,
- * so we will start with it disabled.
- */
- watchdog_counter = WATCHDOG_IS_STARTED_DISABLED;
- }
- else
- {
- /* The watchdog was not initialized in the MACHINE_DRIVER.
- * But it has been manually started, so we will default to
- * using a vblank watchdog. We will set up a default time
- * of 3 times the refresh rate. Which is 3 seconds @ 60Hz
- * refresh.
-
- * The 3 seconds delay is targeted at qzshowby, which otherwise
- * would reset at the start of a game.
- */
- watchdog_counter = 3 * ATTOSECONDS_TO_HZ(machine->screen[0].refresh);
- }
- }
-}
-
-
-
-/*************************************
- *
- * Watchdog reset
- *
- *************************************/
-
-void watchdog_reset(running_machine *machine)
-{
- if (watchdog_counter == WATCHDOG_IS_TIMER_BASED)
- {
- timer_reset(watchdog_timer, machine->drv->watchdog_time);
- }
- else
- {
- if (watchdog_counter == WATCHDOG_IS_STARTED_DISABLED)
- {
- watchdog_counter = WATCHDOG_IS_BEING_STARTED;
- logerror("(vblank) watchdog armed by reset\n");
- }
-
- watchdog_setup(machine, FALSE);
- }
-}
-
-
-
-/*************************************
- *
- * Watchdog enable/disable
- *
- *************************************/
-
-void watchdog_enable(running_machine *machine, int enable)
-{
- if (!enable)
- {
- // Disable all timers
- watchdog_counter = WATCHDOG_IS_DISABLED;
- }
- else
- // Setup only on change from disable to enable.
- // Do not setup if watchdog is disabled from machine init.
- if (watchdog_counter == WATCHDOG_IS_DISABLED)
- {
- watchdog_counter = WATCHDOG_IS_BEING_STARTED;
- watchdog_setup(machine, FALSE);
- }
-}
-
-
-
-#if 0
-#pragma mark -
-#pragma mark CPU SCHEDULING
-#endif
-
-/*************************************
- *
- * Execute all the CPUs for one
- * timeslice
- *
- *************************************/
+/*-------------------------------------------------
+ cpuexec_timeslice - execute all CPUs for a
+ single timeslice
+-------------------------------------------------*/
void cpuexec_timeslice(running_machine *machine)
{
@@ -552,12 +396,37 @@ void cpuexec_timeslice(running_machine *machine)
-/*************************************
- *
- * Abort the timeslice for the
- * active CPU
- *
- *************************************/
+/***************************************************************************
+ CPU SCHEDULING
+***************************************************************************/
+
+/*-------------------------------------------------
+ cpu_boost_interleave - temporarily boosts the
+ interleave factor
+-------------------------------------------------*/
+
+void cpu_boost_interleave(attotime timeslice_time, attotime boost_duration)
+{
+ /* if you pass 0 for the timeslice_time, it means pick something reasonable */
+ if (attotime_compare(timeslice_time, perfect_interleave) < 0)
+ timeslice_time = perfect_interleave;
+
+ LOG(("cpu_boost_interleave(%s, %s)\n", attotime_string(timeslice_time, 9), attotime_string(boost_duration, 9)));
+
+ /* adjust the interleave timer */
+ timer_adjust(interleave_boost_timer, timeslice_time, 0, timeslice_time);
+
+ /* adjust the end timer, but only if we are going to extend it */
+ if (!timer_enabled(interleave_boost_timer_end) || attotime_compare(timer_timeleft(interleave_boost_timer_end), boost_duration) < 0)
+ timer_adjust(interleave_boost_timer_end, boost_duration, 0, attotime_never);
+}
+
+
+/*-------------------------------------------------
+ activecpu_abort_timeslice - abort execution
+ for the current timeslice, allowing other
+ CPUs to run before we run again
+-------------------------------------------------*/
void activecpu_abort_timeslice(void)
{
@@ -574,39 +443,10 @@ void activecpu_abort_timeslice(void)
}
-
-/*************************************
- *
- * Return the current local time for
- * a CPU, relative to the current
- * timeslice
- *
- *************************************/
-
-attotime cpunum_get_localtime(int cpunum)
-{
- attotime result;
-
- VERIFY_CPUNUM(cpunum_get_localtime);
-
- /* if we're active, add in the time from the current slice */
- result = cpu[cpunum].localtime;
- if (cpunum == cpu_getexecutingcpu())
- {
- int cycles = cycles_currently_ran();
- result = attotime_add(result, ATTOTIME_IN_CYCLES(cycles, cpunum));
- }
- return result;
-}
-
-
-
-/*************************************
- *
- * Set a suspend reason for the
- * given CPU
- *
- *************************************/
+/*-------------------------------------------------
+ cpunum_suspend - set a suspend reason for the
+ given CPU
+-------------------------------------------------*/
void cpunum_suspend(int cpunum, int reason, int eatcycles)
{
@@ -621,13 +461,10 @@ void cpunum_suspend(int cpunum, int reason, int eatcycles)
}
-
-/*************************************
- *
- * Clear a suspend reason for a
- * given CPU
- *
- *************************************/
+/*-------------------------------------------------
+ cpunum_resume - clear a suspend reason for the
+ given CPU
+-------------------------------------------------*/
void cpunum_resume(int cpunum, int reason)
{
@@ -641,13 +478,11 @@ void cpunum_resume(int cpunum, int reason)
}
-
-/*************************************
- *
- * Return true if a given CPU is
- * suspended
- *
- *************************************/
+/*-------------------------------------------------
+ cpunum_is_suspended - returns true if the
+ given CPU is suspended for any of the given
+ reasons
+-------------------------------------------------*/
int cpunum_is_suspended(int cpunum, int reason)
{
@@ -657,60 +492,56 @@ int cpunum_is_suspended(int cpunum, int reason)
-/*************************************
- *
- * Gets the current CPU's clock speed
- *
- *************************************/
+/***************************************************************************
+ CPU CLOCK MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ update_clock_information - recomputes clock
+ information for the specified CPU
+-------------------------------------------------*/
-int cpunum_get_clock(int cpunum)
+static void update_clock_information(running_machine *machine, int cpunum)
{
- VERIFY_CPUNUM(cpunum_get_clock);
- return cpu[cpunum].clock;
-}
+ /* recompute cps and spc */
+ cycles_per_second[cpunum] = (double)cpu[cpunum].clock * cpu[cpunum].clockscale;
+ attoseconds_per_cycle[cpunum] = ATTOSECONDS_PER_SECOND / ((double)cpu[cpunum].clock * cpu[cpunum].clockscale);
+ /* re-compute the perfect interleave factor */
+ compute_perfect_interleave(machine);
+}
-/*************************************
- *
- * Sets the current CPU's clock speed
- *
- *************************************/
+/*-------------------------------------------------
+ cpunum_get_clock - gets the given CPU's
+ clock speed
+-------------------------------------------------*/
-void cpunum_set_clock(running_machine *machine, int cpunum, int clock)
+int cpunum_get_clock(int cpunum)
{
- VERIFY_CPUNUM(cpunum_set_clock);
-
- cpu[cpunum].clock = clock;
- cycles_per_second[cpunum] = (double)clock * cpu[cpunum].clockscale;
- attoseconds_per_cycle[cpunum] = ATTOSECONDS_PER_SECOND / ((double)clock * cpu[cpunum].clockscale);
-
- /* re-compute the perfect interleave factor */
- compute_perfect_interleave(machine);
+ VERIFY_CPUNUM(cpunum_get_clock);
+ return cpu[cpunum].clock;
}
+/*-------------------------------------------------
+ cpunum_set_clock - sets the given CPU's
+ clock speed
+-------------------------------------------------*/
-void cpunum_set_clock_period(running_machine *machine, int cpunum, attoseconds_t clock_period)
+void cpunum_set_clock(running_machine *machine, int cpunum, int clock)
{
VERIFY_CPUNUM(cpunum_set_clock);
- cpu[cpunum].clock = ATTOSECONDS_PER_SECOND / clock_period;
- cycles_per_second[cpunum] = (double) (ATTOSECONDS_PER_SECOND / clock_period) * cpu[cpunum].clockscale;
- attoseconds_per_cycle[cpunum] = clock_period;
-
- /* re-compute the perfect interleave factor */
- compute_perfect_interleave(machine);
+ cpu[cpunum].clock = clock;
+ update_clock_information(machine, cpunum);
}
-
-/*************************************
- *
- * Returns the current scaling factor
- * for a CPU's clock speed
- *
- *************************************/
+/*-------------------------------------------------
+ cpunum_get_clockscale - returns the current
+ scaling factor for a CPU's clock speed
+-------------------------------------------------*/
double cpunum_get_clockscale(int cpunum)
{
@@ -719,105 +550,83 @@ double cpunum_get_clockscale(int cpunum)
}
-
-/*************************************
- *
- * Sets the current scaling factor
- * for a CPU's clock speed
- *
- *************************************/
+/*-------------------------------------------------
+ cpunum_set_clockscale - sets the current
+ scaling factor for a CPU's clock speed
+-------------------------------------------------*/
void cpunum_set_clockscale(running_machine *machine, int cpunum, double clockscale)
{
VERIFY_CPUNUM(cpunum_set_clockscale);
cpu[cpunum].clockscale = clockscale;
- cycles_per_second[cpunum] = (double)cpu[cpunum].clock * clockscale;
- attoseconds_per_cycle[cpunum] = ATTOSECONDS_PER_SECOND / ((double)cpu[cpunum].clock * clockscale);
-
- /* re-compute the perfect interleave factor */
- compute_perfect_interleave(machine);
+ update_clock_information(machine, cpunum);
}
-/*************************************
- *
- * Temporarily boosts the interleave
- * factor
- *
- *************************************/
-
-void cpu_boost_interleave(attotime timeslice_time, attotime boost_duration)
-{
- /* if you pass 0 for the timeslice_time, it means pick something reasonable */
- if (attotime_compare(timeslice_time, perfect_interleave) < 0)
- timeslice_time = perfect_interleave;
-
- LOG(("cpu_boost_interleave(%s, %s)\n", attotime_string(timeslice_time, 9), attotime_string(boost_duration, 9)));
-
- /* adjust the interleave timer */
- timer_adjust(interleave_boost_timer, timeslice_time, 0, timeslice_time);
-
- /* adjust the end timer, but only if we are going to extend it */
- if (!timer_enabled(interleave_boost_timer_end) || attotime_compare(timer_timeleft(interleave_boost_timer_end), boost_duration) < 0)
- timer_adjust(interleave_boost_timer_end, boost_duration, 0, attotime_never);
-}
-
+/***************************************************************************
+ CPU TIMING
+***************************************************************************/
+/*-------------------------------------------------
+ cpunum_get_localtime - returns the current
+ local time for a CPU
+-------------------------------------------------*/
-#if 0
-#pragma mark -
-#pragma mark TIMING HELPERS
-#endif
+attotime cpunum_get_localtime(int cpunum)
+{
+ attotime result;
-/*************************************
- *
- * Return cycles ran this iteration
- *
- *************************************/
+ VERIFY_CPUNUM(cpunum_get_localtime);
-int cycles_currently_ran(void)
-{
- VERIFY_EXECUTINGCPU(cycles_currently_ran);
- return cycles_running - activecpu_get_icount();
+ /* if we're active, add in the time from the current slice */
+ result = cpu[cpunum].localtime;
+ if (cpunum == cpu_getexecutingcpu())
+ {
+ int cycles = cycles_running - activecpu_get_icount();
+ result = attotime_add(result, ATTOTIME_IN_CYCLES(cycles, cpunum));
+ }
+ return result;
}
-
-/*************************************
- *
- * Return total number of CPU cycles
- * for the active CPU or for a given CPU.
- *
- *************************************/
+/*-------------------------------------------------
+ activecpu_gettotalcycles - return the total
+ number of CPU cycles executed on the active
+ CPU
+-------------------------------------------------*/
UINT64 activecpu_gettotalcycles(void)
{
VERIFY_ACTIVECPU(activecpu_gettotalcycles);
if (activecpu == cpu_getexecutingcpu())
- return cpu[activecpu].totalcycles + cycles_currently_ran();
+ return cpu[activecpu].totalcycles + cycles_running - activecpu_get_icount();
else
return cpu[activecpu].totalcycles;
}
+
+/*-------------------------------------------------
+ cpunum_gettotalcycles - return the total
+ number of CPU cycles executed on the
+ specified CPU
+-------------------------------------------------*/
+
UINT64 cpunum_gettotalcycles(int cpunum)
{
VERIFY_CPUNUM(cpunum_gettotalcycles);
if (cpunum == cpu_getexecutingcpu())
- return cpu[cpunum].totalcycles + cycles_currently_ran();
+ return cpu[cpunum].totalcycles + cycles_running - activecpu_get_icount();
else
return cpu[cpunum].totalcycles;
}
-
-/*************************************
- *
- * Safely eats cycles so we don't
- * cross a timeslice boundary
- *
- *************************************/
+/*-------------------------------------------------
+ activecpu_eat_cycles - safely eats cycles so
+ we don't cross a timeslice boundary
+-------------------------------------------------*/
void activecpu_eat_cycles(int cycles)
{
@@ -829,97 +638,112 @@ void activecpu_eat_cycles(int cycles)
-/*************************************
- *
- * Scales a given value by the fraction
- * of time elapsed between refreshes
- *
- *************************************/
+/***************************************************************************
+ SYNCHRONIZATION HELPERS
+***************************************************************************/
-int cpu_scalebyfcount(int value)
+/*-------------------------------------------------
+ cpu_suspend_until_trigger - suspend execution
+ until the given trigger fires
+-------------------------------------------------*/
+
+static void cpunum_suspend_until_trigger(int cpunum, int trigger, int eatcycles)
{
- attotime refresh_elapsed = timer_timeelapsed(refresh_timer);
- int result;
+ /* suspend the CPU immediately if it's not already */
+ cpunum_suspend(cpunum, SUSPEND_REASON_TRIGGER, eatcycles);
- /* shift off some bits to ensure no overflow */
- if (value < 65536)
- result = value * (refresh_elapsed.attoseconds >> 16) / (refresh_period.attoseconds >> 16);
- else
- result = value * (refresh_elapsed.attoseconds >> 32) / (refresh_period.attoseconds >> 32);
- if (value >= 0)
- return (result < value) ? result : value;
- else
- return (result > value) ? result : value;
+ /* set the trigger */
+ cpu[cpunum].trigger = TRIGGER_TIMESLICE;
}
+/*-------------------------------------------------
+ cpu_yield - yield our current timeslice
+-------------------------------------------------*/
-#if 0
-#pragma mark -
-#pragma mark VIDEO TIMING
-#endif
+void cpu_yield(void)
+{
+ int cpunum = cpu_getexecutingcpu();
+ VERIFY_EXECUTINGCPU(cpu_yielduntil_trigger);
+ cpunum_suspend_until_trigger(cpunum, TRIGGER_TIMESLICE, FALSE);
+}
-/*************************************
- *
- * Computes the VBLANK timing
- *
- *************************************/
-void cpu_compute_vblank_timing(running_machine *machine)
+/*-------------------------------------------------
+ cpu_spin - burn CPU cycles until our timeslice
+ is up
+-------------------------------------------------*/
+
+void cpu_spin(void)
{
- refresh_period = attotime_make(0, machine->screen[0].refresh);
+ int cpunum = cpu_getexecutingcpu();
+ VERIFY_EXECUTINGCPU(cpu_yielduntil_trigger);
+ cpunum_suspend_until_trigger(cpunum, TRIGGER_TIMESLICE, TRUE);
+}
- /* recompute the vblank period */
- vblank_period = attotime_make(0, machine->screen[0].refresh / (vblank_multiplier ? vblank_multiplier : 1));
- if (vblank_timer != NULL && timer_enable(vblank_timer, FALSE))
- {
- attotime remaining = timer_timeleft(vblank_timer);
- if (remaining.seconds == 0 && remaining.attoseconds == 0)
- remaining = vblank_period;
- timer_adjust(vblank_timer, remaining, 0, vblank_period);
- }
- LOG(("cpu_compute_vblank_timing: refresh=%s vblank=%s\n", attotime_string(refresh_period, 9), attotime_string(vblank_period, 9)));
-}
+/*-------------------------------------------------
+ cpu_spinuntil_trigger - burn CPU cycles until
+ a timer trigger
+-------------------------------------------------*/
+void cpu_spinuntil_trigger(int trigger)
+{
+ int cpunum = cpu_getexecutingcpu();
+ VERIFY_EXECUTINGCPU(cpu_yielduntil_trigger);
+ cpunum_suspend_until_trigger(cpunum, trigger, TRUE);
+}
-/*************************************
- *
- * Returns the VBLANK state
- *
- *************************************/
+/*-------------------------------------------------
+ cpunum_spinuntil_trigger - burn specified CPU
+ cycles until a timer trigger
+-------------------------------------------------*/
-int cpu_getvblank(void)
+void cpunum_spinuntil_trigger(int cpunum, int trigger)
{
- return vblank;
+ VERIFY_CPUNUM(cpunum_spinuntil_trigger);
+ cpunum_suspend_until_trigger(cpunum, trigger, TRUE);
}
+/*-------------------------------------------------
+ cpu_spinuntil_int - burn CPU cycles until the
+ next interrupt
+-------------------------------------------------*/
-/*************************************
- *
- * Returns the current frame count
- *
- *************************************/
+void cpu_spinuntil_int(void)
+{
+ int cpunum = cpu_getexecutingcpu();
+ VERIFY_EXECUTINGCPU(cpu_spinuntil_int);
+ cpunum_suspend_until_trigger(cpunum, TRIGGER_INT + cpunum, TRUE);
+}
-int cpu_getcurrentframe(void)
+
+/*-------------------------------------------------
+ cpu_spinuntil_time - burn CPU cycles for a
+ specific period of time
+-------------------------------------------------*/
+
+void cpu_spinuntil_time(attotime duration)
{
- return current_frame;
+ static int timetrig = 0;
+ int cpunum = cpu_getexecutingcpu();
+ VERIFY_EXECUTINGCPU(cpu_spinuntil_time);
+ cpunum_suspend_until_trigger(cpunum, TRIGGER_SUSPENDTIME + timetrig, TRUE);
+ cpu_triggertime(duration, TRIGGER_SUSPENDTIME + timetrig);
+ timetrig = (timetrig + 1) % 256;
}
-#if 0
-#pragma mark -
-#pragma mark SYNCHRONIZATION
-#endif
+/***************************************************************************
+ TRIGGERS
+***************************************************************************/
-/*************************************
- *
- * Generate a specific trigger
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_trigger - generate a trigger now
+-------------------------------------------------*/
void cpu_trigger(running_machine *machine, int trigger)
{
@@ -946,12 +770,10 @@ void cpu_trigger(running_machine *machine, int trigger)
}
-
-/*************************************
- *
- * Generate a trigger in the future
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_triggertime - generate a trigger after a
+ specific period of time
+-------------------------------------------------*/
static TIMER_CALLBACK( cpu_triggertime_callback )
{
@@ -965,12 +787,10 @@ void cpu_triggertime(attotime duration, int trigger)
}
-
-/*************************************
- *
- * Generate a trigger for an int
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_triggerint - generate a trigger
+ corresponding to an interrupt on the given CPU
+-------------------------------------------------*/
void cpu_triggerint(running_machine *machine, int cpunum)
{
@@ -979,136 +799,153 @@ void cpu_triggerint(running_machine *machine, int cpunum)
-/*************************************
- *
- * Burn/yield CPU cycles until a trigger
- *
- *************************************/
-
-void cpu_spinuntil_trigger(int trigger)
-{
- int cpunum = cpu_getexecutingcpu();
-
- VERIFY_EXECUTINGCPU(cpu_spinuntil_trigger);
+/***************************************************************************
+ WATCHDOG TIMERS
+***************************************************************************/
- /* suspend the CPU immediately if it's not already */
- cpunum_suspend(cpunum, SUSPEND_REASON_TRIGGER, 1);
+/*-------------------------------------------------
+ watchdog_callback - watchdog timer callback
+-------------------------------------------------*/
- /* set the trigger */
- cpu[cpunum].trigger = trigger;
+static TIMER_CALLBACK( watchdog_callback )
+{
+ logerror("reset caused by the (time) watchdog\n");
+ mame_schedule_soft_reset(machine);
}
-void cpunum_spinuntil_trigger( int cpunum, int trigger )
-{
- VERIFY_CPUNUM(cpunum_spinuntil_trigger);
- /* suspend the CPU immediately if it's not already */
- cpunum_suspend(cpunum, SUSPEND_REASON_TRIGGER, 1);
+/*-------------------------------------------------
+ watchdog_reset - reset the watchdog timer
+-------------------------------------------------*/
- /* set the trigger */
- cpu[cpunum].trigger = trigger;
+void watchdog_reset(running_machine *machine)
+{
+ /* if we're not enabled, skip it */
+ if (!watchdog_enabled)
+ timer_adjust(watchdog_timer, attotime_never, 0, attotime_zero);
+
+ /* VBLANK-based watchdog? */
+ else if (machine->drv->watchdog_vblank_count != 0)
+ watchdog_counter = machine->drv->watchdog_vblank_count;
+
+ /* timer-based watchdog? */
+ else if (attotime_compare(machine->drv->watchdog_time, attotime_zero) != 0)
+ timer_adjust(watchdog_timer, machine->drv->watchdog_time, 0, attotime_zero);
+
+ /* default to an obscene amount of time (3 seconds) */
+ else
+ timer_adjust(watchdog_timer, ATTOTIME_IN_SEC(3), 0, attotime_zero);
}
+/*-------------------------------------------------
+ watchdog_enable - reset the watchdog timer
+-------------------------------------------------*/
-/*************************************
- *
- * Burn/yield CPU cycles until an
- * interrupt
- *
- *************************************/
-
-void cpu_spinuntil_int(void)
+void watchdog_enable(running_machine *machine, int enable)
{
- VERIFY_EXECUTINGCPU(cpu_spinuntil_int);
- cpu_spinuntil_trigger(TRIGGER_INT + activecpu);
+ /* when re-enabled, we reset our state */
+ if (watchdog_enabled != enable)
+ {
+ watchdog_enabled = enable;
+ watchdog_reset(machine);
+ }
}
-/*************************************
- *
- * Burn/yield CPU cycles until the
- * end of the current timeslice
- *
- *************************************/
-
-void cpu_spin(void)
-{
- cpu_spinuntil_trigger(TRIGGER_TIMESLICE);
-}
+/***************************************************************************
+ CHEESY FAKE VIDEO TIMING
+***************************************************************************/
+/*-------------------------------------------------
+ cpu_compute_vblank_timing - recompute cheesy
+ VBLANK timing after a video change
+-------------------------------------------------*/
-void cpu_yield(void)
+void cpu_compute_vblank_timing(running_machine *machine)
{
- int cpunum = cpu_getexecutingcpu();
-
- VERIFY_EXECUTINGCPU(cpu_yielduntil_trigger);
+ refresh_period = attotime_make(0, machine->screen[0].refresh);
- /* suspend the CPU immediately if it's not already */
- cpunum_suspend(cpunum, SUSPEND_REASON_TRIGGER, 0);
+ /* recompute the vblank period */
+ vblank_period = attotime_make(0, machine->screen[0].refresh / (vblank_multiplier ? vblank_multiplier : 1));
+ if (vblank_timer != NULL && timer_enable(vblank_timer, FALSE))
+ {
+ attotime remaining = timer_timeleft(vblank_timer);
+ if (remaining.seconds == 0 && remaining.attoseconds == 0)
+ remaining = vblank_period;
+ timer_adjust(vblank_timer, remaining, 0, vblank_period);
+ }
- /* set the trigger */
- cpu[cpunum].trigger = TRIGGER_TIMESLICE;
+ LOG(("cpu_compute_vblank_timing: refresh=%s vblank=%s\n", attotime_string(refresh_period, 9), attotime_string(vblank_period, 9)));
}
+/*-------------------------------------------------
+ cpu_scalebyfcount - scale by time between
+ refresh timers
+-------------------------------------------------*/
-/*************************************
- *
- * Burn/yield CPU cycles for a
- * specific period of time
- *
- *************************************/
-
-void cpu_spinuntil_time(attotime duration)
+int cpu_scalebyfcount(int value)
{
- static int timetrig = 0;
+ attotime refresh_elapsed = timer_timeelapsed(refresh_timer);
+ int result;
- cpu_spinuntil_trigger(TRIGGER_SUSPENDTIME + timetrig);
- cpu_triggertime(duration, TRIGGER_SUSPENDTIME + timetrig);
- timetrig = (timetrig + 1) & 255;
+ /* shift off some bits to ensure no overflow */
+ if (value < 65536)
+ result = value * (refresh_elapsed.attoseconds >> 16) / (refresh_period.attoseconds >> 16);
+ else
+ result = value * (refresh_elapsed.attoseconds >> 32) / (refresh_period.attoseconds >> 32);
+ if (value >= 0)
+ return (result < value) ? result : value;
+ else
+ return (result > value) ? result : value;
}
+/*-------------------------------------------------
+ cpu_getiloops - return the cheesy VBLANK
+ interrupt counter (deprecated)
+-------------------------------------------------*/
-#if 0
-#pragma mark -
-#pragma mark CORE TIMING
-#endif
+int cpu_getiloops(void)
+{
+ VERIFY_ACTIVECPU(cpu_getiloops);
+ return cpu[activecpu].iloops;
+}
-/*************************************
- *
- * Returns the number of times the
- * interrupt handler will be called
- * before the end of the current
- * video frame.
- *
- *************************************/
-/*--------------------------------------------------------------
+/*-------------------------------------------------
+ cpu_getvblank - return the cheesy VBLANK
+ state (deprecated)
+-------------------------------------------------*/
- This can be useful to interrupt handlers to synchronize
- their operation. If you call this from outside an interrupt
- handler, add 1 to the result, i.e. if it returns 0, it means
- that the interrupt handler will be called once.
+int cpu_getvblank(void)
+{
+ return vblank;
+}
---------------------------------------------------------------*/
-int cpu_getiloops(void)
+/*-------------------------------------------------
+ cpu_getcurrentframe - return the current
+ frame count (deprecated)
+-------------------------------------------------*/
+
+int cpu_getcurrentframe(void)
{
- VERIFY_ACTIVECPU(cpu_getiloops);
- return cpu[activecpu].iloops;
+ return current_frame;
}
-/*************************************
- *
- * Hook for updating things on the
- * real VBLANK (once per frame)
- *
- *************************************/
+/***************************************************************************
+ INTERNAL TIMING
+***************************************************************************/
+
+/*-------------------------------------------------
+ cpu_vblankreset - hook for updating things on
+ cheesy fake VBLANK (once per frame)
+-------------------------------------------------*/
static void cpu_vblankreset(running_machine *machine)
{
@@ -1121,14 +958,8 @@ static void cpu_vblankreset(running_machine *machine)
input_port_vblank_start();
/* check the watchdog */
- if (watchdog_counter > 0)
- {
- if (--watchdog_counter == 0)
- {
- logerror("reset caused by the (vblank) watchdog\n");
- mame_schedule_soft_reset(machine);
- }
- }
+ if (machine->drv->watchdog_vblank_count != 0 && --watchdog_counter == 0)
+ watchdog_callback(machine, NULL, 0);
/* reset the cycle counters */
for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
@@ -1141,12 +972,10 @@ static void cpu_vblankreset(running_machine *machine)
}
-
-/*************************************
- *
- * First-run callback for VBLANKs
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_firstvblankcallback - timer callback for
+ the first fake VBLANK
+-------------------------------------------------*/
static TIMER_CALLBACK( cpu_firstvblankcallback )
{
@@ -1158,12 +987,10 @@ static TIMER_CALLBACK( cpu_firstvblankcallback )
}
-
-/*************************************
- *
- * VBLANK core handler
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_vblankcallback - timer callback for
+ subsequent fake VBLANKs
+-------------------------------------------------*/
static TIMER_CALLBACK( cpu_vblankcallback )
{
@@ -1231,12 +1058,10 @@ static TIMER_CALLBACK( cpu_vblankcallback )
}
-
-/*************************************
- *
- * End-of-VBLANK callback
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_updatecallback - timer callback for
+ the fake end of VBLANK
+-------------------------------------------------*/
static TIMER_CALLBACK( cpu_updatecallback )
{
@@ -1256,18 +1081,15 @@ static TIMER_CALLBACK( cpu_updatecallback )
}
-
-/*************************************
- *
- * Callback for timed interrupts
- * (not tied to a VBLANK)
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_timedintcallback - timer callback for
+ timed interrupts
+-------------------------------------------------*/
static TIMER_CALLBACK( cpu_timedintcallback )
{
/* bail if there is no routine */
- if (machine->drv->cpu[param].timed_interrupt && !cpunum_is_suspended(param, SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE))
+ if (machine->drv->cpu[param].timed_interrupt != NULL && !cpunum_is_suspended(param, SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE))
{
cpuintrf_push_context(param);
(*machine->drv->cpu[param].timed_interrupt)(machine, param);
@@ -1276,12 +1098,10 @@ static TIMER_CALLBACK( cpu_timedintcallback )
}
-
-/*************************************
- *
- * Callback to force a timeslice
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_timeslicecallback - timer callback for
+ timeslicing
+-------------------------------------------------*/
static TIMER_CALLBACK( cpu_timeslicecallback )
{
@@ -1289,13 +1109,10 @@ static TIMER_CALLBACK( cpu_timeslicecallback )
}
-
-/*************************************
- *
- * Callback to end a temporary
- * interleave boost
- *
- *************************************/
+/*-------------------------------------------------
+ end_interleave_boost - timer callback to end
+ temporary interleave boost
+-------------------------------------------------*/
static TIMER_CALLBACK( end_interleave_boost )
{
@@ -1304,13 +1121,10 @@ static TIMER_CALLBACK( end_interleave_boost )
}
-
-/*************************************
- *
- * Compute the "perfect" interleave
- * interval
- *
- *************************************/
+/*-------------------------------------------------
+ compute_perfect_interleave - compute the
+ "perfect" interleave interval
+-------------------------------------------------*/
static void compute_perfect_interleave(running_machine *machine)
{
@@ -1340,18 +1154,18 @@ static void compute_perfect_interleave(running_machine *machine)
}
-
-/*************************************
- *
- * Setup all the core timers
- *
- *************************************/
+/*-------------------------------------------------
+ cpu_inittimers - set up all the core timers
+-------------------------------------------------*/
static void cpu_inittimers(running_machine *machine)
{
attotime first_time;
int cpunum, max, ipf;
+ /* allocate a timer for the watchdog */
+ watchdog_timer = timer_alloc(watchdog_callback, NULL);
+
/* allocate a dummy timer at the minimum frequency to break things up */
ipf = machine->drv->cpu_slices_per_frame;
if (ipf <= 0)
@@ -1449,4 +1263,3 @@ static void cpu_inittimers(running_machine *machine)
/* reset the refresh timer to get ourself back in sync */
timer_adjust(refresh_timer, attotime_never, 0, attotime_never);
}
-