예제 #1
0
/* Returns the number of remaining events that can occur on this freq counter
 * while respecting <freq> events per period, and taking into account that
 * <pend> events are already known to be pending. Returns 0 if limit was reached.
 */
unsigned int freq_ctr_remain_period(struct freq_ctr_period *ctr, unsigned int period,
				    unsigned int freq, unsigned int pend)
{
	unsigned int curr, past;
	unsigned int remain;

	curr = ctr->curr_ctr;
	past = ctr->prev_ctr;

	remain = ctr->curr_tick + period - now_ms;
	if (likely((int)remain < 0)) {
		/* We're past the first period, check if we can still report a
		 * part of last period or if we're too far away.
		 */
		past = curr;
		curr = 0;
		remain += period;
		if ((int)remain < 0)
			past = 0;
	}
	if (likely(past))
		curr += div64_32((unsigned long long)past * remain, period);

	curr += pend;
	freq -= curr;
	if ((int)freq < 0)
		freq = 0;
	return freq;
}
예제 #2
0
/* Reads a frequency counter taking history into account for missing time in
 * current period. The period has to be passed in number of ticks and must
 * match the one used to feed the counter. The counter value is reported for
 * current date (now_ms). The return value has the same precision as one input
 * data sample, so low rates over the period will be inaccurate but still
 * appropriate for max checking. One trick we use for low values is to specially
 * handle the case where the rate is between 0 and 1 in order to avoid flapping
 * while waiting for the next event.
 *
 * For immediate limit checking, it's recommended to use freq_ctr_period_remain()
 * instead which does not have the flapping correction, so that even frequencies
 * as low as one event/period are properly handled.
 *
 * For measures over a 1-second period, it's better to use the implicit functions
 * above.
 */
unsigned int read_freq_ctr_period(struct freq_ctr_period *ctr, unsigned int period)
{
	unsigned int curr, past;
	unsigned int remain;

	curr = ctr->curr_ctr;
	past = ctr->prev_ctr;

	remain = ctr->curr_tick + period - now_ms;
	if (unlikely((int)remain < 0)) {
		/* We're past the first period, check if we can still report a
		 * part of last period or if we're too far away.
		 */
		remain += period;
		if ((int)remain < 0)
			return 0;
		past = curr;
		curr = 0;
	}
	if (past <= 1 && !curr)
		return past; /* very low rate, avoid flapping */

	curr += div64_32((unsigned long long)past * remain, period);
	return curr;
}
예제 #3
0
파일: fixed.c 프로젝트: 1847123212/QuadPawn
static cell AMX_NATIVE_CALL n_fmuldiv(AMX *amx,const cell *params)
{
#if !USE_ANSI_C
#if defined __WATCOMC__ && defined __386__

  cell __fmuldiv(void);
  cell a=params[1];
  cell b=params[2];
  cell c=params[3];

  if (c==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */

  #pragma aux __fmuldiv = \
    "mov    eax, [a]"     \
    "mov    ecx, [c]"     \
    "imul   [b]"          \
    "mov    ebx, ecx"     \
    "shr    ecx, 1"       \
    "add    eax, ecx"     \
    "adc    edx, 0"       \
    "idiv   ebx"          \
    "mov    [a], eax"     \
    modify [eax ebx ecx edx];
  __fmuldiv();
  return a;

#elif _MSC_VER>=9 && defined _WIN32

  __int64 a;
  cell divisor=params[3];
  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */
  a=((__int64)params[1] * (__int64)params[2] + (__int64)(divisor/2)) / (__int64)divisor;
  return (cell)a;

#elif defined __BORLANDC__  && __BORLANDC__ >= 0x500  && (defined __32BIT__ || defined __WIN32__)

  __int64 a;
  cell divisor=params[3];
  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */
  a=((__int64)params[1] * (__int64)params[2] + (__int64)(divisor/2)) / (__int64)divisor;
  return (cell)a;

#elif defined __GNUC__

  long long a;
  cell divisor=params[3];
  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */
  a=((long long)params[1] * (long long)params[2] + (long long)(divisor/2)) / (long long)divisor;
  return (cell)a;

#else
  #error Unsupported compiler configuration, but USE_ANSI_C is false
#endif

#else // USE_ANSI_C

  ucell a,b,c,d;
  ucell v[2];
  cell sign=1;
  cell divisor=params[3];

  assert(MULTIPLIER<=(1L<<16));

  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */

  /* make all three operands positive values, but keep the sign of the result */
  if (params[1]<0) {
    ((cell*)params)[1]=-params[1];
    sign=-sign;     /* negate result */
  } /* if */
  if (params[2]<0) {
    ((cell*)params)[2]=-params[2];
    sign=-sign;     /* negate result */
  } /* if */
  if (divisor<0) {
    divisor=-divisor;
    sign=-sign;     /* negate result */
  } /* if */

  a = HIWORD(params[1]);
  b = LOWORD(params[1]);
  c = HIWORD(params[2]);
  d = LOWORD(params[2]);

  /* store the intermediate into a 64-bit/128-bit number */
  v[1]=c*a;
  v[0]=d*b;
  ADD_WRAP(v[0],v[1],d*a << WORDSHIFT);
  ADD_WRAP(v[0],v[1],c*b << WORDSHIFT);

  /* add half of the divisor, to round the data */
  ADD_WRAP(v[0],v[1],(ucell)divisor/2);

  /* if the divisor is smaller than v[1], the result will not fit in a cell */
  if ((ucell)divisor<v[1]) {
    amx_RaiseError(amx,AMX_ERR_DOMAIN);
    return 0;
  } /* if */

  return (cell)div64_32(v,(ucell)divisor) * sign;
#endif
}
예제 #4
0
파일: fixed.c 프로젝트: 1847123212/QuadPawn
static cell AMX_NATIVE_CALL n_fdiv(AMX *amx,const cell *params)
{
#if !USE_ANSI_C
#if defined __WATCOMC__ && defined __386__

  cell __fdiv(void);
  cell a=params[1];
  cell b=params[2];
  #if MULTIPLIER != 1000
    #error Assembler chunks must be modified for a different base
  #endif

  if (b==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */

  #pragma aux __fdiv =    \
    "mov    eax, [a]"     \
    "mov    ecx, [b]"     \
    "cdq"                 \
    "mov    ebx, 1000"    \
    "imul   ebx"          \
    "mov    ebx, ecx"     \
    "shr    ecx, 1"       \
    "add    eax, ecx"     \
    "adc    edx, 0"       \
    "idiv   ebx"          \
    "mov    [a], eax"     \
    modify [eax ebx ecx edx];
  __fdiv();
  return a;

#elif _MSC_VER>=9 && defined _WIN32

  __int64 a;
  cell divisor=params[2];
  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */
  a=((__int64)params[1] * (__int64)MULTIPLIER + (__int64)(divisor/2)) / (__int64)divisor;
  return (cell)a;

#elif defined __BORLANDC__  && __BORLANDC__ >= 0x500  && (defined __32BIT__ || defined __WIN32__)

  __int64 a;
  cell divisor=params[2];
  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */
  a=((__int64)params[1] * (__int64)MULTIPLIER + (__int64)(divisor/2)) / (__int64)divisor;
  return (cell)a;

#elif defined __GNUC__

  long long a;
  cell divisor=params[2];
  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_DIVIDE);
    return 0;
  } /* if */
  a=((long long)params[1] * (long long)MULTIPLIER + (long long)(divisor/2)) / (long long)divisor;
  return (cell)a;

#else
  #error Unsupported compiler configuration, but USE_ANSI_C is false
#endif

#else // USE_ANSI_C

  /* The dividend must be scaled prior to division. The dividend
   * is a 32-bit number, however, so when shifted, it will become
   * a value that no longer fits in a 32-bit variable. This routine
   * does the division by using only 16-bit and 32-bit values, but
   * with considerable effort.
   * If your compiler supports 64-bit integers, modify this routine
   * to use them. If your processor can do a simple 64-bit by 32-bit
   * division in assembler, write assembler chunks.
   * In other words: the straight C routine that follows is correct
   * and portable, but use it only as a last resort.
   *
   * This function was adapted from source code that appeared in
   * Dr. Dobb's Journal, August 1992, page 117.
   */

  cell dividend=params[1];
  cell divisor=params[2];
  cell sign=1;
  ucell b[2];

  if (divisor==0) {
    amx_RaiseError(amx,AMX_ERR_NATIVE);
    return 0;
  } /* if */

  /* make both operands positive values, but keep the sign of the result */
  if (dividend<0) {
    dividend=-dividend;
    sign=-sign;     /* negate result */
  } /* if */
  if (divisor<0) {
    divisor=-divisor;
    sign=-sign;     /* negate result */
  } /* if */

  /* pre-scale the dividend into a 64-bit/128-bit number */
  b[0]=dividend*MULTIPLIER;
  b[1]=(HIWORD(dividend)*MULTIPLIER) >> WORDSHIFT;

  /* add half of the divisor, to round the data */
  b[0]+=(ucell)divisor/2;
  if (b[0]<(ucell)divisor/2)
    b[1]+=1;  /* wrap-around ocurred */

  /* if the divisor is smaller than b[1], the result will not fit in a cell */
  if ((ucell)divisor<b[1]) {
    amx_RaiseError(amx,AMX_ERR_DOMAIN);
    return 0;
  } /* if */

  return (cell)div64_32(b,(ucell)divisor) * sign;
#endif
}
예제 #5
0
파일: fixed.c 프로젝트: 1847123212/QuadPawn
static cell AMX_NATIVE_CALL n_fmul(AMX *amx,const cell *params)
{
#if !USE_ANSI_C
#if defined __WATCOMC__ && defined __386__

  cell __fmul(void);
  cell a=params[1];
  cell b=params[2];
  #if MULTIPLIER != 1000
    #error Assembler chunks must be modified for a different base
  #endif
  #pragma aux __fmul =    \
    "mov    eax, [a]"     \
    "mov    ebx, 1000"    \
    "imul   [b]"          \
    "add    eax, 500"     \
    "adc    edx, 0"       \
    "idiv   ebx"          \
    "mov    [a], eax"     \
    modify [eax ebx edx];
  __fmul();
  (void)amx;
  return a;

#elif _MSC_VER>=9 && defined _WIN32

  __int64 a=(__int64)params[1] * (__int64)params[2];
  a=(a+MULTIPLIER/2) / MULTIPLIER;
  (void)amx;
  return (cell)a;

#elif defined __BORLANDC__  && __BORLANDC__ >= 0x500 && (defined __32BIT__ || defined __WIN32__)

  __int64 a=(__int64)params[1] * (__int64)params[2];
  a=(a+MULTIPLIER/2) / MULTIPLIER;
  (void)amx;
  return (cell)a;

#elif defined __GNUC__

  long long a=(long long)params[1] * (long long)params[2];
  a=(a+MULTIPLIER/2) / MULTIPLIER;
  (void)amx;
  return (cell)a;

#else
  #error Unsupported compiler configuration, but USE_ANSI_C is false
#endif

#else // USE_ANSI_C

  /* (Xs * Ys) == (X*Y)ss, where "s" stands for scaled.
   * The desired result is (X*Y)s, so we must unscale once.
   * but we cannot do this before multiplication, because of loss
   * of precision, and we cannot do it after the multiplication
   * because of the possible overflow.
   * The technique used here is to cut the multiplicands into
   * components and to multiply these components separately:
   *
   * Assume Xs == (A << 16) + B and Ys == (C << 16) + D, where A, B,
   * C and D are 16 bit numbers.
   *
   *    A B
   *    C D
   *    --- *
   *    D*B + (D*A << 16) + (C*B << 16) + (C*A << (16+16))
   *
   * Thus we have built a 64-bit number, which can now be scaled back
   * to 32-bit by dividing by the scale factor.
   */
  #define ADD_WRAP(var,carry,expr)  (((var)+=(expr)), ((carry)+=((var)<(expr)) ? 1 : 0))
  ucell a,b,c,d;
  ucell v[2];
  cell sign=1;

  (void)amx;
  assert(MULTIPLIER<=(1L<<WORDSHIFT));

  /* make both operands positive values, but keep the sign of the result */
  if (params[1]<0) {
    ((cell*)params)[1]=-params[1];
    sign=-sign;     /* negate result */
  } /* if */
  if (params[2]<0) {
    ((cell*)params)[2]=-params[2];
    sign=-sign;     /* negate result */
  } /* if */

  a = HIWORD(params[1]);
  b = LOWORD(params[1]);
  c = HIWORD(params[2]);
  d = LOWORD(params[2]);

  /* store the intermediate into a 64-bit/128-bit number */
  v[1]=c*a;
  v[0]=d*b;
  ADD_WRAP(v[0],v[1],d*a << WORDSHIFT);
  ADD_WRAP(v[0],v[1],c*b << WORDSHIFT);

  /* add half of the divisor, to round the data */
  ADD_WRAP(v[0],v[1],MULTIPLIER/2);

  /* if the divisor is smaller than v[1], the result will not fit in a cell */
  if (MULTIPLIER<v[1]) {
    amx_RaiseError(amx,AMX_ERR_DOMAIN);
    return 0;
  } /* if */

  return (cell)div64_32(v,MULTIPLIER) * sign;
#endif
}
예제 #6
0
static unsigned long do_fast_gettimeoffset(void)
{
#ifdef CONFIG_PM
	unsigned long pc0;
	unsigned long offset;

	pc0 = au_readl(SYS_TOYREAD);
	if (pc0 < last_pc0) {
		offset = 0xffffffff - last_pc0 + pc0;
		printk("offset over: %x\n", (unsigned)offset);
	}
	else {
		offset = (unsigned long)(((pc0 - last_pc0) * 305) / 10);
	}
	if ((pc0-last_pc0) > 2*MATCH20_INC) {
		printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n",
				(unsigned)offset, (unsigned)last_pc0,
				(unsigned)last_match20, (unsigned)pc0);
	}
	au_sync();
	return offset;
#else
	u32 count;
	unsigned long res, tmp;
	unsigned long r0;

	/* Last jiffy when do_fast_gettimeoffset() was called. */
	static unsigned long last_jiffies=0;
	unsigned long quotient;

	/*
	 * Cached "1/(clocks per usec)*2^32" value.
	 * It has to be recalculated once each jiffy.
	 */
	static unsigned long cached_quotient=0;

	tmp = jiffies;

	quotient = cached_quotient;

	if (tmp && last_jiffies != tmp) {
		last_jiffies = tmp;
		if (last_jiffies != 0) {
			r0 = div64_32(timerhi, timerlo, tmp);
			quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0);
			cached_quotient = quotient;
		}
	}

	/* Get last timer tick in absolute kernel time */
	count = read_c0_count();

	/* .. relative to previous jiffy (32 bits is enough) */
	count -= timerlo;

	__asm__("multu\t%1,%2\n\t"
		"mfhi\t%0"
		:"=r" (res)
		:"r" (count),
		 "r" (quotient));

	/*
 	 * Due to possible jiffies inconsistencies, we need to check
	 * the result so that we'll get a timer that is monotonic.
	 */
	if (res >= USECS_PER_JIFFY)
		res = USECS_PER_JIFFY-1;

	return res;
#endif
}
예제 #7
0
파일: addrlib.cpp 프로젝트: chemecse/mesa
UINT_32 __umoddi3(UINT_64 n, UINT_32 base)
{
    return div64_32(n, base);
}