int main ()
{
  double d, d1, d2;
  float f, f1, f2;
  unsigned long long ull, a, b;
  long long ll;
  int i;

#ifdef __powerpc64__
  ull = __rldcl (a, b, 3);
  ull = __rldcr (a, b, 3);
  ull = __rldic (a, 3, 4);
  ull = __rldicl (a, 4, 5);
  ull = __rldicr (a, 2, 3);
  ull = __rldimi (a, b, 4, 6);
#endif
  ull = __rlwimi (a, b, 6, 9, 12);
  ull = __rlwnm (a, b, 3, 5);
  d = __fmul (d1, d2);
  f = __fmuls (f1, f2);
  f = __frsp (f);
  d = __fcfid (ll);
  d = __frsqrte (d1);
  ll = __fctid (d);
  ll = __fctidz (d);
  i = __fctiw (d);
  i = __fctiwz (d);

  __protected_stream_count (1, 2);
  __protected_stream_go ();
  __protected_stream_set (1, 0x1000, 3);
  __protected_stream_stop (3);
  __protected_stream_stop_all ();
  __protected_unlimited_stream_set (3, 0x1000, 1);

  return 0;
}
Beispiel #2
0
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
}