// @(#) $Header: /home/abrown/public_html/first/first2002chs/software2002/simulator/RCS/pb_math.c,v 1.11 2006/12/14 21:19:03 abrown Exp $
// Allen Brown  date="20061214 13:17:38"

/***********************************************************************
  * Copyright (C) 2002  Allen Brown
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  * 
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the
  *   Free Software Foundation, Inc.
  *   59 Temple Place, Suite 330
  *   Boston, MA  02111-1307  USA
  * 
  * To contact the author of this software:
  *   Allen Brown
  *   PO Box J
  *   Corvallis, OR
  * 
  *   http://brown.armoredpenguin.com/~abrown/contact.html
  ***********************************************************************/

#include <stdio.h>
#include "pb.h"

// The ramarray is memory accessible only via the get and put commands.
#define RAMSIZE 64
int ramarray[RAMSIZE];

#define pbmasktrue(width)	(1 << width)
#define pbmaskfalse(width)	(~pbmasktrue(width) & 0xff)
#define pbbittopos(value,width)	((0x01 & value) << width)
#define pbbitfrpos(value,width)	(((value & 0xff) >> width) & 0x01)
#define pbextractbit(value,width)	(width<0 ? (value & 0x01) : pbbitfrpos(value,width) )
// #define pbwordorbit(value,width)	(width<0 ? (value&0xff) : pbbitfrpos(value,width))
#define pbwordorbit(value,width)	(width<0 ? (value) : pbbitfrpos(value,width))

// --------------------------------------------------------------
// pblet - Basic Stamp Manual p.?
// If valuea is just a bit (widtha>=0) then set the bit
// pointed to by widtha from the lsb of valueb.  Otherwise
// set valuea=valueb.
void pblet(unsigned int *valuea, int widtha, unsigned int valueb, int widthb,
	   char valuea_name[], char line_n[])
{
  unsigned int valuebshift;
  if( widtha < 0 )
    {
      printf("\tpblet (w8) '%s': '%s' %d(%x)",
	     line_n, valuea_name, *valuea, *valuea);
      *valuea = 0xff & pbwordorbit(valueb,widthb);
      printf(" -> %d(%x).\n", *valuea, *valuea); fflush(stdout);
    } else {
      printf("\tpblet (bit%d) '%s': '%s' %d(%x)",
	     widtha, line_n, valuea_name, *valuea, *valuea);
      valuebshift = pbbittopos(pbextractbit(valueb,widthb),widtha);
      *valuea = ((*valuea & pbmaskfalse(widtha)) | valuebshift);
      printf(" & %d(%x) -> %d(%x).\n",
	     valuebshift, valuebshift, *valuea, *valuea); fflush(stdout);
    }
  if( valuea_name[0] == 'o'  &&  valuea_name[1] == 'u'
      &&  valuea_name[2] == 't')
    {
      printf("output: %d\n", *valuea );
    }
  return;
} // pblet

// --------------------------------------------------------------
// pbstrip - Converts a number pair to a single C int.
int pbstrip(int valuea, int widtha)
{
  int valuea_;
  valuea_=pbwordorbit(valuea,widtha);
  return(valuea_);
} // pbstrip

// --------------------------------------------------------------
// pbabs - Basic Stamp Manual p.64
int pbabs(int valuea, int widtha)
{
  int valuea_;
  valuea_=pbwordorbit(valuea,widtha);
  return( abs(valuea_) );
} // pbabs

// --------------------------------------------------------------
// pbbnot - Basic Stamp Manual p.64
int pbbnot(int valuea, int widtha)
{
  int valuea_;
  valuea_=pbwordorbit(valuea,widtha);
  return(~valuea_);
} // pbbnot

// --------------------------------------------------------------
// pbadd - Basic Stamp Manual p.67
int pbadd(int valuea, int widtha, int valueb, int widthb)
{
  int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  //  printf("**pbadd: %x/%x/%d + %x/%x/%d",
  //	 valuea_, valuea, widtha, valueb_, valueb, widthb);
  //  printf(" = %x\n", (valuea_ + valueb_) & 0xff);
  return( valuea_ + valueb_ );
} // pbadd

// --------------------------------------------------------------
// pbsub - Basic Stamp Manual p.67
int pbsub(int valuea, int widtha, int valueb, int widthb)
{
  int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return( valuea_ - valueb_ );
} // pbsub

// --------------------------------------------------------------
// pbmul - Basic Stamp Manual p.67
int pbmul(int valuea, int widtha, int valueb, int widthb)
{
  int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return( valuea_ * valueb_ );
} // pbmul

// --------------------------------------------------------------
// pbdiv - Basic Stamp Manual p.69
int pbdiv(unsigned int valuea, int widtha, unsigned int valueb, int widthb)
{
  unsigned int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return( valuea_ / valueb_ );
} // pbdiv

// --------------------------------------------------------------
// pbmin - Basic Stamp Manual p.70
// Note that the min function of pbasic actually is returning the
// max of the two numbers.  Sigh...
int pbmin(unsigned int valuea, int widtha, unsigned int valueb, int widthb)
{
  unsigned int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return(valuea_>valueb_ ? valuea_ : valueb_);
} // pbmin

// --------------------------------------------------------------
// pbmax - Basic Stamp Manual p.71
// Note that the max function of pbasic actually is returning the
// min of the two numbers.  Sigh...
int pbmax(unsigned int valuea, int widtha, unsigned int valueb, int widthb)
{
  unsigned int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return(valuea_<valueb_ ? valuea_ : valueb_);
} // pbmax

// --------------------------------------------------------------
// pbband - Basic Stamp Manual p.73
int pbband(int valuea, int widtha, int valueb, int widthb)
{
  int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return(valuea_ & valueb_);
} // pbband

// --------------------------------------------------------------
// pbbor - Basic Stamp Manual p.73
int pbbor(int valuea, int widtha, int valueb, int widthb)
{
  int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return(valuea_ | valueb_);
} // pbbor

// --------------------------------------------------------------
// pbget - Basic Stamp Manual p.127
void pbget(int *valuea, int widtha, int valueb, int widthb)
{
  if( valueb >= RAMSIZE )
    {
      fprintf(stderr,"pbget: valueb=%x > %x.\n", valueb, RAMSIZE );
    } else {
      *valuea = 0xff & ramarray[pbwordorbit(valueb,widthb)];
      // printf("\tpbget: get %x from [%x].\n", *valuea, pbwordorbit(valueb,widthb));
    }
  return;
} // pbget

// --------------------------------------------------------------
// pbput - Basic Stamp Manual p.245
void pbput(int valuea, int widtha, int valueb, int widthb)
{
  if( valuea >= RAMSIZE )
    {
      fprintf(stderr,"pbput: valuea=%x > %x.\n", valuea, RAMSIZE );
    } else {
      // printf("\tpbput: store %x to [%x].\n", pbwordorbit(valueb,widthb), valuea);
      ramarray[valuea] = 0xff & pbwordorbit(valueb,widthb);
    }
  return;
} // pbput

// --------------------------------------------------------------
// pbeq - Basic Stamp Manual p.149
int pbeq(unsigned int valuea, int widtha, unsigned int valueb, int widthb)
{
  unsigned int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return(valuea_ == valueb_);
} // pbeq

// --------------------------------------------------------------
// pblt - Basic Stamp Manual p.149
int pblt(unsigned int valuea, int widtha, unsigned int valueb, int widthb)
{
  unsigned int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return(valuea_ < valueb_);
} // pblt

// --------------------------------------------------------------
// pble - Basic Stamp Manual p.149
int pble(unsigned int valuea, int widtha, unsigned int valueb, int widthb)
{
  unsigned int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  return(valuea_ <= valueb_);
} // pble

// --------------------------------------------------------------
// pbgt - Basic Stamp Manual p.149
int pbgt(unsigned int valuea, int widtha, unsigned int valueb, int widthb)
{
  unsigned int valuea_, valueb_;
  valuea_=pbwordorbit(valuea,widtha);
  valueb_=pbwordorbit(valueb,widthb);
  //  printf("**pbgt: %x/%x/%d + %x/%x/%d",
  //  	 valuea, valuea_, widtha, valueb, valueb_, widthb);
  //  printf(" '>' => %x\n", (valuea_ > valueb_));
  return(valuea_ > valueb_);
} // pbgt

// --------------------------------------------------------------
// pblor - Basic Stamp Manual p.149
int pblor(int valuea, int widtha, int valueb, int widthb)
{
  int valuea_, valueb_;
  valuea_=(0 != pbwordorbit(valuea,widtha));
  valueb_=(0 != pbwordorbit(valueb,widthb));
  return(valuea_ || valueb_);
} // pblor

// --------------------------------------------------------------
/* TODO:
 * - Make and check pbge,pbne
 * - create pbbshl, pbbshr (bit shift).
 */

