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;
}