// @(#) $Header: /home/abrown/public_html/first/first2003chs/software/simulator/RCS/pb_support.c,v 2.6 2006/12/14 19:40:16 abrown Exp $

/***********************************************************************
  * Copyright (C) 2002, 2003  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 "pb.h"
#include <stdio.h>


// --------------------------------------------------------------
#define PBVALUESIZE 200
static pbvalue pbvaluearray[PBVALUESIZE];
static pbvalueindex = PBVALUESIZE;

// --------------------------------------------------------------
// pbtokencmp - Compare two PB tokens, ignoring case.
// Return 1 if same, 0 if different.
int pbtokencmp(char *pbtoken1, char *pbtoken2)
{
  int index;

  while( *pbtoken1 || *pbtoken2 )
    {
      if( 
	 ( tolower(*pbtoken1) != tolower(*pbtoken2) )
	 | ( *pbtoken1 == (char) 0 )
	 | ( *pbtoken2 == (char) 0 )
	)
	{
	  return(0); // Different
	}
      pbtoken1++;
      pbtoken2++;
    }
  return(1); // Same
} // pbtokencmp

// --------------------------------------------------------------
// printnumber
void printnumber(char *stringa, struct pbnumber numbera, char *stringb)
{
  pbvalue valuea;

  valuea = numbera.vpoint ? *numbera.vpoint : numbera.value;
  printf("%s{%x,%hd,%hd,'%s'}%s",
	 stringa,
	 valuea, numbera.size, numbera.index, numbera.name,
	 stringb);
  fflush(stdout);
  return;
} // printnumber

// --------------------------------------------------------------
// makemask - Create an and'able or or'able mask from description.
// Return the maskvalue corresponding to the fieldsize, shifted
// by fieldindex.  If fieldinvert is true, invert the mask.
pbvalue makemask( int fieldinvert, pbi fieldsize, pbi fieldindex )
{
  pbvalue maskvalue = 0xffff; // All ones.
  maskvalue = ~(maskvalue << fieldsize); // Shift 0's in from right and invert.
  maskvalue = maskvalue << fieldindex; // Now move the mask to the index pos.
  if( fieldinvert )
    {
      maskvalue = 0xffff & ~maskvalue;
    } else {
      maskvalue = 0xffff & maskvalue;
    }
  // printf("makemask(%d,%hd,%hd)=%x;\n", fieldinvert, fieldsize, fieldindex, maskvalue); fflush(stdout);
  return(maskvalue);
} // makemask

// --------------------------------------------------------------
// makepbnumber
// Since C doesn't allow structs to be created on the fly,
// this function is provided for that purpose.  We need this
// when dealing with constants.
struct pbnumber makepbnumber(
		      pbvalue *vpoint,
		      pbvalue initvalue,
		      pbi size,
		      pbi index,
		      char *name
		      )
{
  struct pbnumber numbera;
  numbera.vpoint = vpoint;
  if( !vpoint )
    { // If no storage location specified, we use the value field
      numbera.value = initvalue;	// and initialize it.
    }
  numbera.size = size;
  numbera.index = index;
  numbera.name = name;

  // printnumber("makepbnumber: ",numbera,";\n");
  return( numbera );
} // makepbnumber

// --------------------------------------------------------------
// makepbconst
// Since C doesn't allow structs to be created on the fly,
// this function is provided for that purpose.  We need this
// when dealing with constants.
struct pbnumber makepbconst(
		      pbvalue value,
		      pbi size,
		      char *name
		      )
{
  struct pbnumber numbera;
  
  numbera.vpoint = 0;
  numbera.value = value;
  numbera.size = size;
  numbera.index = 0;
  numbera.name = name;

  // printnumber("makepbconst: ",numbera,";\n");
  return( numbera );
} // makepbconst

// --------------------------------------------------------------
// pbstrip - Converts a pbnumber to a pbvalue.
pbvalue pbstrip(struct pbnumber numbera)
{
  pbvalue valuea_, valueb_;
  valueb_ = numbera.vpoint ? *numbera.vpoint : numbera.value;
  valuea_ = makemask(0,numbera.size,0) & (valueb_ >> numbera.index);
  valuea_ = ((-1^0xff)*((valuea_)>>15)|(valuea_));
  return(valuea_);
} // pbstrip

// --------------------------------------------------------------
// assertpbnumber - Complain if the pbnumber doesn't match what we expect.
int assertpbnumber(struct pbnumber numbera, struct pbnumber numberb, char *comment)
{
  int cmpvalue, cmpsize, cmpindex, cmpname;
  pbvalue valuea, valueb;
  valuea = numbera.vpoint ? *numbera.vpoint : numbera.value;
  valueb = numberb.vpoint ? *numberb.vpoint : numberb.value;

  cmpvalue = valuea == valueb;
  cmpsize = numbera.size == numberb.size;
  cmpindex = numbera.index == numberb.index;
  cmpname = pbtokencmp( numbera.name, numberb.name );
  if( cmpvalue && cmpsize && cmpindex && cmpname )
    {
      return(0);
    } else {
      printf("ASSERT FAIL:");
      if( cmpname )
	{
	  printf("  name='%s'", (int)numbera.name);
	} else {
	  printf("  name='%s'!='%s'", (int)numbera.name, (int)numberb.name);
	}
      if( cmpvalue )
	{
	  printf("  value=%d(0x%x)", (int)valuea, (int)valueb);
	} else {
	  printf("  value=%d(0x%x)!=%d(0x%x)",
		 (int)valuea, (int)valuea,
		 (int)valueb, (int)valueb
		);
	}
      if( cmpsize )
	{
	  printf("  size=%d(0x%x)", (int)numbera.size, (int)numbera.size);
	} else {
	  printf("  size=%d(0x%x)!=%d(0x%x)",
		 (int)numbera.size, (int)numbera.size,
		 (int)numberb.size, (int)numberb.size
		);
	}
      if( cmpindex )
	{
	  printf("  index=%d(0x%x)", (int)numbera.index, (int)numbera.index);
	} else {
	  printf("  index=%d(0x%x)!=%d(0x%x)",
		 (int)numbera.index, (int)numbera.index,
		 (int)numberb.index, (int)numberb.index
		);
	}
      printf(", %s\n", comment); fflush(stdout);
      return(1);
    }
} // assertpbnumber

// --------------------------------------------------------------
// TODO:

