AUSAM/source/mac/mac/mac11.c

#include	"mac.h"
#include	"mac.x"


/*
 *   Define constant routines.
 */
prdc1()
{
	prdc(0);
	return;
}

prdc2()
{
	prdc(1);
	return;
}

prdc3()
{
	prdc(2);
	return;
}

prdc4()
{
	prdc(3);
	return;
}

prdc(n)
register int n;
{
	p = intercode.i_opr;
	if (!*p)  {
		synerr("expression required");
		return;
		}

	/*
	 *   Bump pc up by the length of the constant.
	 */
	locn[lcntr].l_value =+ head.dctype[n].f_len;

	return;
}



/*
 *   Special dc.
 *	Can define strings or constants.
 */
prdcs()
{
	register struct fd *f;
	register int len;

	/*
	 *   Allow a string, or a single expr.
	 */

	f = &head.dctype[4];
	if (!f->f_len)  {
		/* dc has not been declared in the r-file */
		synerr("dc not allowed");
		return;
		}

	p = intercode.i_opr;

	if (*p == '"')  {
		p++;
		len = 0;
		while (*p++ != '"')
			len++;

		locn[lcntr].l_value =+ (len * f->f_len);
		return;
		}

	/*
	 *   Expr.
	 */

	locn[lcntr].l_value =+ f->f_len;
	return;
}



/*
 *   Null routine - just return.
 */
prnull()
{
	return;
}



/*
 *   Equate a label to a value. (defined expression)
 *   A check has already been made for a re-defined
 *   label tag.
 */
prequ()
{
	register struct	st *q;
	register int l;

	p = intercode.i_opr;		/* operand field */
	l = intercode.i_label;
	if (l == ERR)  {
		synerr("label tag required");
		return;
		}

	q = &symtab[l];
	q->s_value = expr();
	q->s_mode =| reloc;

	return;
}


/*
 *   Turn on global indicator.
 *   Useful only for loader format output.
 */
prglobal()
{
	register struct	st *q;
	register int i;

	p = intercode.i_opr;
	if (*p++ != '$')  {
		synerr("label required");
		return;
		}

	i = argnum();
	q = &symtab[i];
	q->s_mode =| GLOB;

	return;
}


/*
 *   Align pc to an even multiple of expr().
 *   If already at the boundary - no align done.
 */
pralign()
{
	register int v;
	register int l;

	p = intercode.i_opr;
	v = expr();
	if (v < 1)
		return;
	l = locn[lcntr].l_value;
	v = (l + v) % v;
	if (!v)
		/* no align needed */
		return;

	locn[lcntr].l_value =+ v;
	return;
}


/*
 *   Set origin of pc
 */
prorg()
{
	register int v;
	register int l;

	p = intercode.i_opr;
	v = expr();
	if (v < 0)  {
		synerr("negative org");
		return;
		}

	/*
	 *   Check l_limit:
	 *	if backwards org, check that l_limit
	 *	is max(l_limit, l_value).
	 *
	 *	This is so that we know the overall
	 *	size of a code segment for pass 2.
	 *
	 *   Check l_start:
	 *	if no code generated yet - set start addr of
	 *	code to v;
	 *	else ensure l_start = min(l_start, v);
	 *
	 *   This will NOT work if the user orgs, generates
	 *	code, then orgs to zero and doesn't generate
	 *	any code.
	 */
	if (!locn[lcntr].l_value)
		/*
		 *   No code - initialise start addr
		 */
		locn[lcntr].l_start = v;
	else
		if (v < locn[lcntr].l_start)
			/*
			 *   Lower org than we have - remember it.
			 */
			locn[lcntr].l_start = v;

	/*
	 *   Check limit.
	 */
	l = locn[lcntr].l_value;
	if (v < l  &&  l > locn[lcntr].l_limit)
		locn[lcntr].l_limit = l;

	locn[lcntr].l_value = v;		/* org pc */
	return;
}


/*
 *   Set segment indicator
 */
prseg()
{
	register int v;
	register int l;

	p = intercode.i_opr;
	v = expr();
	if (v < 0 || v >= LCOUNT)  {
		synerr("no such location counter");
		return;
		}

	lcntr = v;
	return;
}


/*
 *   Reserve (n) bu's of null storage.
 */
prds()
{
	register int v;
	register int l;

	p = intercode.i_opr;
	v = expr();
	if (v < 0)  {
		synerr("negative ds");
		return;
		}

	locn[lcntr].l_value =+ v;
	return;
}


/*
 *   end:   Set eof flag, and check symbol table.
 *	    (not ref, undefined etc)
 */
prend()
{
	register struct	st *q;
	register int n;

	eof = TRUE;			/* set end-of-source flag */
	q = symtab;			/* start of symbol table */

	n = 0;
	while (q < coreptr)  {
		if (!(q->s_mode & DEFN)  &&  !(q->s_mode & GLOB))  {
			n++;
			printf("label %-8s is undefined\n", q->s_name);
			}

		q++;				/* next symbol */
		}

	if (n)
		synerr("Undefined labels");

	return;
}


/*
 *   Structure offset definition.
 */
prstruc()
{
	register struct st *q;
	register int l;

	p = intercode.i_opr;		/* operand field */
	l = intercode.i_label;

	if (l != ERR)  {
		/* Equate label to struct offset now */
		q = &symtab[l];
		q->s_value = nstruc;
		}

	nstruc =+ expr();

	return;
}



/*
 *   End structure offset counter.
 */
prends()
{
	register struct st *q;
	register int l;

	l = intercode.i_label;
	if (l != ERR)  {
		q = &symtab[l];
		q->s_value = nstruc;
		}

	/* Reset structure counter */
	nstruc = 0;
	return;
}