/*
**  This file is part of Zterp, and is
**  Copyright 1992, 1993 Charles Hannum
*/

#include <sys/types.h>
#include "main.h"
#include "variable.h"
#include "arithmetic.h"
#include "jump.h"

void
or (a, b)
  uword a, b;
{
  store_variable_push (a | b);
}

void
and (a, b)
  uword a, b;
{
  store_variable_push (a & b);
}

void
add (a, b)
  sword a, b;
{
  store_variable_push (a + b);
}

void
subtract (a, b)
  sword a, b;
{
  store_variable_push (a - b);
}

void
multiply (a, b)
  sword a, b;
{
  store_variable_push (a * b);
}

void
divide (a, b)
  sword a, b;
{
  store_variable_push (a / b);
}

void
compute_the_modulus (a, b)
  /* Isn't it silly that there is no verb in the English language for this? */
  sword a, b;
{
  store_variable_push (a % b);
}

void
random (x)
  sword x;
{
  static uword max_count = 0;
  static uword counter;
  if (!x)
    store_variable_push (max_count = x);
  else if (!max_count)
    if (x > 0)
    {
      uword a = random_seed[0],
	    b = random_seed[1];
      random_seed[1] = a;
      random_seed[0] ^= (b >> 1) | (a << 15);
      store_variable_push (((random_seed[0] & 0x7fff) % x) + 1);
    }
    else
    {
      max_count = -x;
      counter = 0;
      store_variable_push (0);
    }
  else
  {
    if (x >= 0)
      max_count = x;
    if (++counter > max_count)
      counter = 1;
    store_variable_push (counter);
  }
}

void
increment (n)
  uword n;
{
  store_variable_nopush (n, fetch_variable_nopop (n) + 1);
}

void
decrement (n)
  uword n;
{
  store_variable_nopush (n, fetch_variable_nopop (n) - 1);
}

void
not (x)
  uword x;
{
  store_variable_push (~ x);
}

void
not_or_call_procedure (x)
  uword x;
{
  if (zil_version < 5)
    not (x);
  else
    call_procedure_1 (x);
}

void
logical_shift (a, b)
  uword a;
  sword b;
{
  if (b < 0)
    store_variable_push (a >> (-b));
  else
    store_variable_push (a << b);
}

void
arithmetic_shift (a, b)
  sword a;
  sword b;
{
  if (b < 0)
    if (a < 0)
      store_variable_push (~((~a) >> (-b)));
    else
      store_variable_push (a >> (-b));
  else
    store_variable_push (a << b);
}
