Esempio n. 1
0
attotime &attotime::operator*=(UINT32 factor)
{
	// if one of the items is attotime::never, return attotime::never
	if (seconds >= ATTOTIME_MAX_SECONDS)
		return *this = never;

	// 0 times anything is zero
	if (factor == 0)
		return *this = zero;

	// split attoseconds into upper and lower halves which fit into 32 bits
	UINT32 attolo;
	UINT32 attohi = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);

	// scale the lower half, then split into high/low parts
	UINT64 temp = mulu_32x32(attolo, factor);
	UINT32 reslo;
	temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reslo);

	// scale the upper half, then split into high/low parts
	temp += mulu_32x32(attohi, factor);
	UINT32 reshi;
	temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reshi);

	// scale the seconds
	temp += mulu_32x32(seconds, factor);
	if (temp >= ATTOTIME_MAX_SECONDS)
		return *this = never;

	// build the result
	seconds = temp;
	attoseconds = (attoseconds_t)reslo + mul_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT);
	return *this;
}
Esempio n. 2
0
attotime attotime_mul(attotime _time1, UINT32 factor)
{
	UINT32 attolo, attohi, reslo, reshi;
	UINT64 temp;

	/* if one of the items is attotime_never, return attotime_never */
	if (_time1.seconds >= ATTOTIME_MAX_SECONDS)
		return attotime_never;

	/* 0 times anything is zero */
	if (factor == 0)
		return attotime_zero;

	/* split attoseconds into upper and lower halves which fit into 32 bits */
	attohi = divu_64x32_rem(_time1.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);

	/* scale the lower half, then split into high/low parts */
	temp = mulu_32x32(attolo, factor);
	temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reslo);

	/* scale the upper half, then split into high/low parts */
	temp += mulu_32x32(attohi, factor);
	temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reshi);

	/* scale the seconds */
	temp += mulu_32x32(_time1.seconds, factor);
	if (temp >= ATTOTIME_MAX_SECONDS)
		return attotime_never;

	/* build the result */
	return attotime_make(temp, (attoseconds_t)reslo + mul_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT));
}
Esempio n. 3
0
attotime attotime_div(attotime _time1, UINT32 factor)
{
	UINT32 attolo, attohi, reshi, reslo, remainder;
	attotime result;
	UINT64 temp;

	/* if one of the items is attotime_never, return attotime_never */
	if (_time1.seconds >= ATTOTIME_MAX_SECONDS)
		return attotime_never;

	/* ignore divide by zero */
	if (factor == 0)
		return _time1;

	/* split attoseconds into upper and lower halves which fit into 32 bits */
	attohi = divu_64x32_rem(_time1.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);

	/* divide the seconds and get the remainder */
	result.seconds = divu_64x32_rem(_time1.seconds, factor, &remainder);

	/* combine the upper half of attoseconds with the remainder and divide that */
	temp = (INT64)attohi + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
	reshi = divu_64x32_rem(temp, factor, &remainder);

	/* combine the lower half of attoseconds with the remainder and divide that */
	temp = attolo + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
	reslo = divu_64x32_rem(temp, factor, &remainder);

	/* round based on the remainder */
	result.attoseconds = (attoseconds_t)reslo + mulu_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT);
	if (remainder >= factor / 2)
		if (++result.attoseconds >= ATTOSECONDS_PER_SECOND)
		{
			result.attoseconds = 0;
			result.seconds++;
		}
	return result;
}
Esempio n. 4
0
attotime &attotime::operator/=(UINT32 factor)
{
	// if one of the items is attotime::never, return attotime::never
	if (seconds >= ATTOTIME_MAX_SECONDS)
		return *this = never;

	// ignore divide by zero
	if (factor == 0)
		return *this;

	// split attoseconds into upper and lower halves which fit into 32 bits
	UINT32 attolo;
	UINT32 attohi = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);

	// divide the seconds and get the remainder
	UINT32 remainder;
	seconds = divu_64x32_rem(seconds, factor, &remainder);

	// combine the upper half of attoseconds with the remainder and divide that
	UINT64 temp = (INT64)attohi + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
	UINT32 reshi = divu_64x32_rem(temp, factor, &remainder);

	// combine the lower half of attoseconds with the remainder and divide that
	temp = attolo + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
	UINT32 reslo = divu_64x32_rem(temp, factor, &remainder);

	// round based on the remainder
	attoseconds = (attoseconds_t)reslo + mulu_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT);
	if (remainder >= factor / 2)
		if (++attoseconds >= ATTOSECONDS_PER_SECOND)
		{
			attoseconds = 0;
			seconds++;
		}
	return *this;
}
Esempio n. 5
0
const char *attotime::as_string(int precision) const
{
	static char buffers[8][30];
	static int nextbuf;
	char *buffer = &buffers[nextbuf++ % 8][0];

	// special case: never
	if (*this == never)
		sprintf(buffer, "%-*s", precision, "(never)");

	// case 1: we want no precision; seconds only
	else if (precision == 0)
		sprintf(buffer, "%d", seconds);

	// case 2: we want 9 or fewer digits of precision
	else if (precision <= 9)
	{
		UINT32 upper = attoseconds / ATTOSECONDS_PER_SECOND_SQRT;
		int temp = precision;
		while (temp < 9)
		{
			upper /= 10;
			temp++;
		}
		sprintf(buffer, "%d.%0*d", seconds, precision, upper);
	}

	// case 3: more than 9 digits of precision
	else
	{
		UINT32 lower;
		UINT32 upper = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &lower);
		int temp = precision;
		while (temp < 18)
		{
			lower /= 10;
			temp++;
		}
		sprintf(buffer, "%d.%09d%0*d", seconds, upper, precision - 9, lower);
	}
	return buffer;
}
Esempio n. 6
0
const char *attotime_string(attotime _time, int precision)
{
	static char buffers[8][30];
	static int nextbuf;
	char *buffer = &buffers[nextbuf++ % 8][0];

	/* case 1: we want no precision; seconds only */
	if (precision == 0)
		sprintf(buffer, "%d", _time.seconds);

	/* case 2: we want 9 or fewer digits of precision */
	else if (precision <= 9)
	{
		UINT32 upper = _time.attoseconds / ATTOSECONDS_PER_SECOND_SQRT;
		int temp = precision;
		while (temp < 9)
		{
			upper /= 10;
			temp++;
		}
		sprintf(buffer, "%d.%0*d", _time.seconds, precision, upper);
	}

	/* case 3: more than 9 digits of precision */
	else
	{
		UINT32 lower;
		UINT32 upper = divu_64x32_rem(_time.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &lower);
		int temp = precision;
		while (temp < 18)
		{
			lower /= 10;
			temp++;
		}
		sprintf(buffer, "%d.%09d%0*d", _time.seconds, upper, precision - 9, lower);
	}
	return buffer;
}
Esempio n. 7
0
void device_scheduler::timeslice()
{
	bool call_debugger = ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);

	// build the execution list if we don't have one yet
	if (UNEXPECTED(m_execute_list == nullptr))
		rebuild_execute_list();

	// if the current quantum has expired, find a new one
	while (m_basetime >= m_quantum_list.first()->m_expire)
		m_quantum_allocator.reclaim(m_quantum_list.detach_head());

	// loop until we hit the next timer
	while (m_basetime < m_timer_list->m_expire)
	{
		// by default, assume our target is the end of the next quantum
		attotime target(m_basetime + attotime(0, m_quantum_list.first()->m_actual));

		// however, if the next timer is going to fire before then, override
		if (m_timer_list->m_expire < target)
			target = m_timer_list->m_expire;

		LOG(("------------------\n"));
		LOG(("cpu_timeslice: target = %s\n", target.as_string(PRECISION)));

		// do we have pending suspension changes?
		if (m_suspend_changes_pending)
			apply_suspend_changes();

		// loop over all CPUs
		for (device_execute_interface *exec = m_execute_list; exec != nullptr; exec = exec->m_nextexec)
		{
			// only process if this CPU is executing or truly halted (not yielding)
			// and if our target is later than the CPU's current time (coarse check)
			if (EXPECTED((exec->m_suspend == 0 || exec->m_eatcycles) && target.seconds() >= exec->m_localtime.seconds()))
			{
				// compute how many attoseconds to execute this CPU
				attoseconds_t delta = target.attoseconds() - exec->m_localtime.attoseconds();
				if (delta < 0 && target.seconds() > exec->m_localtime.seconds())
					delta += ATTOSECONDS_PER_SECOND;
				assert(delta == (target - exec->m_localtime).as_attoseconds());

				// if we have enough for at least 1 cycle, do the math
				if (delta >= exec->m_attoseconds_per_cycle)
				{
					// compute how many cycles we want to execute
					int ran = exec->m_cycles_running = divu_64x32(u64(delta) >> exec->m_divshift, exec->m_divisor);
					LOG(("  cpu '%s': %d (%d cycles)\n", exec->device().tag(), delta, exec->m_cycles_running));

					// if we're not suspended, actually execute
					if (exec->m_suspend == 0)
					{
						g_profiler.start(exec->m_profiler);

						// note that this global variable cycles_stolen can be modified
						// via the call to cpu_execute
						exec->m_cycles_stolen = 0;
						m_executing_device = exec;
						*exec->m_icountptr = exec->m_cycles_running;
						if (!call_debugger)
							exec->run();
						else
						{
							debugger_start_cpu_hook(&exec->device(), target);
							exec->run();
							debugger_stop_cpu_hook(&exec->device());
						}

						// adjust for any cycles we took back
						assert(ran >= *exec->m_icountptr);
						ran -= *exec->m_icountptr;
						assert(ran >= exec->m_cycles_stolen);
						ran -= exec->m_cycles_stolen;
						g_profiler.stop();
					}

					// account for these cycles
					exec->m_totalcycles += ran;

					// update the local time for this CPU
					attotime deltatime;
					if (ran < exec->m_cycles_per_second)
						deltatime = attotime(0, exec->m_attoseconds_per_cycle * ran);
					else
					{
						u32 remainder;
						s32 secs = divu_64x32_rem(ran, exec->m_cycles_per_second, &remainder);
						deltatime = attotime(secs, u64(remainder) * exec->m_attoseconds_per_cycle);
					}
					assert(deltatime >= attotime::zero);
					exec->m_localtime += deltatime;
					LOG(("         %d ran, %d total, time = %s\n", ran, s32(exec->m_totalcycles), exec->m_localtime.as_string(PRECISION)));

					// if the new local CPU time is less than our target, move the target up, but not before the base
					if (exec->m_localtime < target)
					{
						target = std::max(exec->m_localtime, m_basetime);
						LOG(("         (new target)\n"));
					}
				}
			}
		}