bits_gram.y 3.57 KB
/* bits_gram.y - Grammar for bit creation  */


%{

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <values.h>

#include "ints.h"

/*
 * tokenString is global holding last ident, string, literal
 * shorn of quotes
 */

#define TOKENSIZ  	256

typedef union _NameType {
   char name[TOKENSIZ];
   int  ival;
} NameType;

typedef struct {
  int val;
  int bits;
} BitDesc;


#define YYSTYPE NameType

/* Forward References */

void    install(char *);
void    install_number(char *);
void    install_hex(char *);
void    install_bin(char *);

/* globals */

int64 Source;  /* extract bits from this 64-bit word */
unsigned short Dest;    /* insert bits into this 16-bit value */
static unsigned short dest;    /* insert bits into this 16-bit value */
char GlobString[512];    /* expression string */

static BitDesc CurDesc;  /* current bit value */
static int line_num = 0;

%}

%start Input

/* Reserved Keywords */


/* symbols */

%token tCOLON
%token tCOMMA
%token tLBRACK
%token tRBRACK
%token tLBRACE
%token tRBRACE
%token tQUIT
%token tEOL

/* patterns */

%token tHEX
%token tBIN
%token tNUMBER
%token tJUNK

%%

Input		: /* EMPTY */
		| Input Statement
;

Statement	: tEOL
		{
		  dest = 0;
		}
		| Line tEOL
		{
		  /* printf("Dest = %04x\n", Dest); */
		  Dest = dest;
		  dest = 0;
		}
;

		  	
Line		: tQUIT
		{
		  return;
		}
		| BitDescription
		{
		  /* printf("Bit Description: val = %04x, bits = %d\n", CurDesc.val,
			CurDesc.bits); */
		  dest = (dest << CurDesc.bits) | CurDesc.val;
		}
		| tNUMBER tLBRACE BitDescription tRBRACE 
		{
		  int i;
		  for(i = 0; i < $1.ival-1; i++)
		    CurDesc.val |= CurDesc.val << CurDesc.bits;
		  CurDesc.bits *= $1.ival;
		  /* printf("Replicate %d times: val = %04x, bits = %d\n", 
		    $1.ival, CurDesc.val, CurDesc.bits); */
		  dest = (dest << CurDesc.bits) | CurDesc.val;
		}
		| Line tCOMMA Line
;

BitDescription	: tNUMBER tHEX
		{
		  CurDesc.bits = $1.ival;
		  CurDesc.val = $2.ival & ((1 << CurDesc.bits) - 1);
		}
		| tNUMBER tBIN
		{
		  CurDesc.bits = $1.ival;
		  CurDesc.val = $2.ival & ((1 << CurDesc.bits) - 1);
		}
		| tLBRACK tNUMBER tRBRACK
		{
		  int word;
		  CurDesc.bits = 1;
		  word = $2.ival / 32; 
		  if(word == 0)
		    CurDesc.val = (Source.word0 >> $2.ival) & 1;
		  else if(word ==1)
		    CurDesc.val = (Source.word1 >> ($2.ival % 32)) & 1;
		  else
		    fprintf(stderr,"Error, bit out range [63:0]:  %d\n", $2.ival);
		}
		| tLBRACK tNUMBER tCOLON tNUMBER tRBRACK
		{
		  int msb, lsb, tmp, width;

		  msb = $2.ival;
		  lsb = $4.ival;

		  if(msb <= lsb) {
		    fprintf(stderr,"Error, first number (%d) in bit range must be larger than second (%d).\n", msb, lsb);
		     tmp = lsb;
		     lsb = msb;
		     msb = tmp;
		   }

		   if(msb > 63) {
		     fprintf(stderr,"Error, MSB (%d) must be <= 63\n", $2.ival); 
		     msb = 63;
		   }

		   width = msb - lsb + 1;	
		   if(width > 16)
		   {	
		     fprintf(stderr,"Error, field width is > 16: %d\n", width);
		     width = 16;
		     lsb = msb - width;
		   }

		   CurDesc.bits = width; 

		   if(msb < 32) /* field in ls word */
		   {
		     CurDesc.val = (Source.word0 >> lsb) & ((1 << width) - 1);
		   }
		   else if(lsb >= 32) /* field in ms word */
		   {
		     CurDesc.val = (Source.word1 >> (lsb % 32)) & ((1 << width) - 1);
		   }
		   else  /* field span ms and ls word */
		   {
		     int lsw, msw, msmask;
		     lsw = 32 - lsb;
		     msw = msb - 32 + 1;
		     msmask = ((1 << msw) - 1) << lsw;
		     CurDesc.val = (Source.word0 >> lsb) & ((1 << lsw) - 1);
		     CurDesc.val |= (Source.word1 << lsw) & msmask;
		   }
		}
;



%%

#include "bits_scan.c"