#include <stdio.h>

/* MSMASM sample source code :

;                                               P                     
;                                             S R     R   P     S S S 
;               R C C             P   S S M M T O I N E   R M   P P P 
;               A A H V M V       M P M M M M R C C U F   O E   A A A 
;             I S S K M A M P N N D M D D D D T         P M M   R R R 
;             S       A P A C U U   D           A A A A C     I E E E 
;         HEX E O O O H H L L H L O   C O C O N C C C C H O O N 0 3 4 
;ADDRESS  NXT L P P P I I O O I O E G E E E E U K K K K K E P C 7 5 6 
;+++++++  +++ + + + + - - - - - - - + - - - - - - - - - + - + - + + + 
 00 XXXX  01  0 0 0 3 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 3 1 0 0 0 RESET
 01 XXXX  02  0 0 0 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 3 1 0 0 0 PRECHARGE
 02 XXXX  03  0 1 0 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 3 1 0 0 0 REQUEST DISPATCH SETUP
;--------------------------------------------------------------------------------------------------------------
 03 0000  03  0 1 0 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 3 1 0 0 0 IDLE
 03 1XXX  04  0 0 3 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 3 1 0 0 0 REFRESH
 03 01XX  06  3 2 0 0 0 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 0 1 2 1 0 0 0 NUBUS SLAVE
 03 001X  18  2 2 0 2 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 ICACHE MISS
 03 0001  09  1 2 3 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 0 0 PROCESSOR

*/

char fname_v[] = {"MSM0.VLA"};
char fname_d[] = {"msm0.hex"};
char xtab[] = {"0123456789ABCDEF"};

char prom[5][2048],p[5];

int a,next_a,isel,rasop,casop,chkop,vmahi,
maphi,vmalo,pclo,nuhi,nulo,pmdoe,pmdg,smdce,
smdoe,mmdce,mmdoe,strtnu,procack,icack,nuack,
refack,pchk,promoe,memop,inc,spare07,spare35,spare46;

char jcond[5];

int prominit[5] = {0x00, 0xc8, 0xc0, 0xff, 0xff};

main(argc,argv)
int argc;
char *argv[];
{
	FILE *fopen(),*f;
	char iline[256];
	int ilen,lnum,k,byte,aa,jmask,jval,sum;
	register int i,j;

	printf("\n*** Falcon Memory State Machine Assembler\n");

	for(i=0; i<2048; i++)
		for(j=0; j<5; j++)
			prom[j][i] = 0;

	if(argc > 1)
		f = fopen(argv[1],"r");
	else
		f = fopen("MSM","r");

	if(f == 0) {
		printf("*** Can't open source file ***");
		exit();
	}
	else printf("*** Source file opened ....\n");

	lnum = 0;
	while(fgets(iline,256,f) != NULL) {
		lnum += 1;
		printf("\rLine %d",lnum);
		ilen = strlen(iline);
		if((ilen > 0) && (iline[0] != ';')) {

			for(i=0; i < 5; i++)
				p[i] = 0;

			sscanf(iline,
			"%x%4s%x%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
			&a,jcond,&next_a,&isel,&rasop,&casop,&chkop,&vmahi,
			&maphi,&vmalo,&pclo,&nuhi,&nulo,&pmdoe,&pmdg,&smdce,
			&smdoe,&mmdce,&mmdoe,&strtnu,&procack,&icack,&nuack,
			&refack,&pchk,&promoe,&memop,&inc,&spare07,&spare35,
			&spare46);

			field(next_a, 0, 0, 128);
			field(isel, 1, 0, 4);
			field(rasop, 2, 2, 4);
			field(casop, 2, 4, 4);
			field(chkop, 2, 6, 4);
			field(memop, 2, 0, 4);
			field(vmahi, 3, 1, 2);
			field(maphi, 3, 3, 2);
			field(vmalo, 3, 2, 2);
			field(pclo, 3, 4, 2);
			field(nuhi, 3, 6, 2);
			field(nulo, 3, 7, 2);
			field(pmdoe, 4, 0, 2);
			field(pmdg, 4, 1, 2);
			field(smdce, 4, 2, 2);
			field(smdoe, 4, 3, 2);
			field(mmdce, 4, 4, 2);
			field(mmdoe, 4, 5, 2);
			field(strtnu, 3, 0, 2);
			field(procack, 1, 2, 2);
			field(icack, 1, 3, 2);
			field(nuack, 1, 4, 2);
			field(refack, 1, 5, 2);
			field(pchk, 1, 6, 2);
			field(promoe, 1, 7, 2);
			field(inc, 4, 7, 2);
			field(spare07, 0, 7, 2);
			field(spare35, 3, 5, 2);
			field(spare46, 4, 6, 2);

			if((a >= 128) || (a < 0))
				printf(" - Illegal address field!!!\n");

			jval = jmask = 0;
			for(i=0; i<4; i++) {
				j = jcond[i];
				switch (j) {
				case '0':
					break;
				case '1':
					jval |= 1 << (3 - i);
					break;
				case 'X':
					jmask |= 1 << (3 - i);
					break;
				default:
					printf(" - Bad jump cond field!!!\n");
					break;
				}
			}

			a = a << 4;
			for(i=0; i < 16; i++) {
				aa = a | (jmask & i) | (~jmask & jval);
				for(j=0; j<5; j++)
					prom[j][aa] = p[j];
			}
		}
	}
	fclose(f);
	printf("\r*** Done reading source file....\n");

	for(i=0; i<5; i++) {
		fname_v[3] = i | '0';
		printf("*** Writing file - %s\n",fname_v);
		f = fopen(fname_v,"w");
		fprintf(f,"$DATA_HEADER$\n$TYPE$\nROM\n$FORMAT$\n");
		fprintf(f,"ADDRESS_DATA\n$BASE$\nD B\n$TOTAL_COLUMNS$");
		fprintf(f,"\n4 8\n$END$\n");
		for(j=0; j<2048; j++) {
			fprintf(f,"%04d ",j);
			for(k=0; k<8; k++) 
				fputc('0' | (1 & (prom[i][j] >> (7 - k))),f);
			fputs("\n",f);
		}
		fclose(f);

		fname_d[3] = i | '0';
		printf("*** Writing file - %s\n",fname_d);
		f = fopen(fname_d,"w");
		fputc(2,f);
		sum = 0;
		for(j=0; j<2048; j++) {
			hex2(f,prom[i][j]);
			fputc(' ',f);
			sum += 0xff & prom[i][j];
		}
		hex2(f,prominit[i]);
	        sum += 0xff & prominit[i];
		fputc(' ',f);
		fputc(3,f);
		fprintf(f,"                \nCHECKSUM=%04x\n",sum & 0xffff);
		
		fclose(f);
	}
	printf("*** Done ...\n");
}

int field(n, byte, bit, max) 
int n,byte,bit,max;
{
	if((n >= max) || (n < 0))
		printf(" - Illegal data in field !!!\n");
	p[byte] |= n << bit;
}


int hex2(f, n)
FILE *f;
int n;
{
	fputc(xtab[15 & (n >> 4)],f);
	fputc(xtab[15 & n],f);
}
