1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-17 00:33:22 +00:00
PDP-10.its/src/c/c34.c
Lars Brinkhoff aec62f3117 Edit SAIL files to be like the originals from ITS.
Rename according to SAIL file C.LIB[C,SYS].  Fix E stuff and remove
trailing ^C and ^@s.
2018-10-30 08:36:56 +01:00

537 lines
11 KiB
C

# include "cc.h"
# include "c3.h"
/*
C COMPILER
Phase C: Code Generator
Section 4: Macro Emitting Routines and Auxiliary Routines
Copyright (c) 1977 by Alan Snyder
*/
/**********************************************************************
ABSTRACT MACHINE INSTRUCTION EMITTING ROUTINES
**********************************************************************/
ilabel(i) {mprint ("%l(*)\n", i);}
jump(i) {mgoto (-c_label, i);}
string() {mprint ("%sr()\n");}
mprolog(n, i, na) {mprint ("%p(*,*,*)\n", n, i, na);}
mepilog() {mprint ("%ep(*,*)\n", nfunc, framesize);}
mgoto(b, o) {mprint ("%go(0,*,*)\n", b, o);}
fcall(n, p, b, o) {mprint ("%ca(*,*,0,*,*)\n", n, p, b, o);}
mreturn() {mprint ("%rt(*)\n", nfunc);}
mtswitch(b, o, l, h, d) {mprint ("%ts(*,*,*,*,*,*)\n", l, -c_label, d, b, o, h);}
mlswitch(b, o, n, d) {mprint ("%ls(*,*,*,*,*)\n", n, -c_label, d, b, o);}
metswitch(b,o,l,h,d) {mprint ("%ets(*,*,*,*,*,*)\n", l, -c_label, d, b, o, h);}
melswitch(b,o,n,d) {mprint ("%els(*,*,*,*,*)\n", n, -c_label, d, b, o);}
endcard() {mprint ("%end()\n");}
mint(i) {mprint ("%in(*)\n", i);}
mlabcon(i) {mprint ("%lc(*)\n", i);}
mpure() {mprint ("%pu()\n");objmode=o_pure;}
mpdata() {mprint ("%pd()\n");objmode=o_pdata;}
ln (p) int *p;
{if (p[1] != lineno)
{lineno = p[1];
mprint ("%ln(*)\n", lineno);
}
}
/**********************************************************************
EMITOP - emit operation given
OP - run-time operator
RB - result base
RO - result offset
B1 - base of operand 1 (optional)
O1 - offset of operand 1 (optional)
B2 - base of operand 2 (optional)
O2 - offset of operand 2 (optional)
**********************************************************************/
emitop (nopr, op, rb, ro, b1, o1, b2, o2)
int op, rb, ro, b1, o1, b2, o2;
{int i;
if ((i = mactab[op]) < 0) errx (1028, op);
else
{cputc ('%', f_mac);
mprd (i);
cputc ('(', f_mac);
mprd (op);
cputc (',', f_mac);
mprd (rb);
cputc (',', f_mac);
mprd (ro);
cputc (',', f_mac);
mprd (b1);
cputc (',', f_mac);
mprd (o1);
if (nopr>1)
{cputc (',', f_mac);
mprd (b2);
cputc (',', f_mac);
mprd (o2);
}
cputc (')', f_mac);
cputc ('\n', f_mac);
}
}
/**********************************************************************
MMOVE - emit macro to accomplish a MOVE
**********************************************************************/
enode *mmove (ep,db,dof,clear_old) enode *ep;
{int ct,op;
ct = ectype (ep);
if (ct == ct_bad) return (NULL);
if (ct == ct_struct)
{errx (2033);
return (NULL);
}
if (ct < ct_char || ct > ct_p3) errx (6024, ct);
op = e_movec + ct - ct_char;
emitop (1, op, db, dof, ep->edref.drbase, ep->edref.droffset);
if (clear_old) eclear (ep);
if (ep->lvalue > 0) ep = mkenode (op, ep->etype, 0, ep, NULL);
ep->edref.drbase = db;
ep->edref.droffset = dof;
ep->saved = 0177;
return (ep);
}
/**********************************************************************
CODE GENERATOR: AUXILIARY ROUTINES
e_alloc
bget1
e_free
intcon
condop
jumpop
invcond
mkenode
tregs
read_node
onebit
fixloc
undfop
max
min
rtyptab
to2p
ro2p
prloc
prtree
*/
/**********************************************************************
E_ALLOC - allocate an ENODE
**********************************************************************/
enode *e_alloc ()
{if (acorp >= acore+(acoresz-1)) errx (4011);
return (acorp++);
}
/**********************************************************************
BGET1 - bit get
**********************************************************************/
int bget1 (w, n) int w, n;
{return ((w>>n) & 1);}
/**********************************************************************
E_FREE - free all ENODEs
**********************************************************************/
e_free ()
{extern enode acore[], *acorp;
acorp = acore;
}
/**********************************************************************
INTCON - create an integer constant expression node
**********************************************************************/
enode *intcon (i)
{return (mkenode (e_int, TINT, 0, i, NULL));}
/**********************************************************************
CONDOP - Is AMOP a conditional?
**********************************************************************/
int condop (op)
{return (op>=e_eqi && op<=e_gep3 || op>=e_jz0 && op<=e_jn3);}
/**********************************************************************
JUMPOP - Is AMOP a jump operation?
**********************************************************************/
int jumpop (op)
{return (condop(op) || op==e_not || op==e_and || op==e_or);}
/**********************************************************************
INVCOND - Return inverse of conditional AMOP
**********************************************************************/
int invtab [] {
1, 0, 5, 4, 3, 2,
7, 6, 11, 10, 9, 8,
13, 12, 17, 16, 15, 14,
19, 18, 23, 22, 21, 20,
25, 24, 29, 28, 27, 26,
31, 30, 35, 34, 33, 32};
int invcond (op)
{if (op>=e_eqi) return (e_eqi + invtab[op-e_eqi]);
if (op>=e_jn0) return (op-4);
return (op+4);
}
/**********************************************************************
MKENODE - create a new expression node, determine its degree
**********************************************************************/
enode *mkenode (op, etype, lvalue, ep1, ep2)
int op, lvalue;
type etype;
enode *ep1, *ep2;
{enode *ep;
ep = e_alloc ();
ep->op = op;
ep->etype = etype;
ep->lvalue = lvalue;
ep->ep1 = ep1;
ep->ep2 = ep2;
ep->degree = 1;
switch (op) {
case e_int:
case e_float:
case e_string:
case e_idn: break;
default: if (!ep1) break;
if (!ep2) ep->degree = ep1->degree;
else if (ep1->degree==ep2->degree)
ep->degree = ep1->degree+1;
else ep->degree = max (ep1->degree, ep2->degree);
}
ep->edref.drbase = ep->edref.droffset = 0;
ep->saved = 0177;
return (ep);
}
/**********************************************************************
TREGS - find registers which can hold a given type
of expression (indicated by 1 bits in the returned word)
**********************************************************************/
int tregs (ep) enode *ep;
{int ct;
ct = ectype (ep);
if (ct >= ct_p0) return (prdt[ct-ct_p0]);
if (ct >= ct_char) return (trdt[ct-ct_char]);
return (0);
}
/**********************************************************************
READ_NODE - Read Node From Node File
**********************************************************************/
read_node ()
{int op, i, j, n;
op = geti (f_node);
if (op<1 || op>n_elist) error (6027, -2, op, lc_node);
*corep++ = op;
i = nodelen[op];
lc_node =+ i;
j = ntw[type_node[op]];
/* read in remaining words of node,
converting offsets to pointers according
to the low-order bits of ntw[] */
while (--i > 0)
{n = geti (f_node);
if (j&1 && n) n = core+(n-flc_node);
*corep++ = n;
j =>> 1;
}
if (op <= 1) eof_node = 1;
return (op);
}
/**********************************************************************
ONEBIT - Return TRUE if word has only 1 bit on.
(Notice the efficiency of this routine. Handling of
high order bit assumes two's complement representation.)
**********************************************************************/
int onebit (w)
{int f;
if (w==0) return (FALSE);
if (w<0) return (-w < 0);
f = FALSE;
do
if (w & 1) if (f) return (FALSE); else f=TRUE;
while (w =>> 1);
return (TRUE);
}
/**********************************************************************
FIXLOC - modify a LOC for an expression
by removing those possibilities
which can never occur, due to the
type of the expression, unless that
would remove all possibilities
**********************************************************************/
fixloc (ep, lp) enode *ep; loc *lp;
{int i;
if (lp->flag == l_mem && ep->op==e_ind)
lp->word =& (tregs(ep->ep1)<<c_indirect)
| ((1<<c_indirect)-1);
else if (lp->flag==l_reg)
{i = lp->word & tregs(ep);
if (i) lp->word = i;
}
}
/**********************************************************************
UNDFOP - is abstract machine operator undefined?
**********************************************************************/
int undfop (op) {return (rtopp[op]<0);}
int max (a, b)
{return (a>b ? a : b);}
int min (a, b)
{return (a<b ? a : b);}
/**********************************************************************
RTYPTAB - Read Type Table
**********************************************************************/
rtyptab ()
{extern int typtab[], *ctypp, *crecp, *etypp, typform[];
register int *p, fmt;
register field *fp;
int f;
f = xopen (fn_typtab, MREAD, BINARY);
etypp = typtab + TTSIZE;
ctypp = typtab + geti (f);
p = typtab;
while (p < ctypp)
{fmt = typform[*p++ = geti (f)];
*p++ = geti (f);
*p++ = geti (f);
switch (fmt) {
case 1: *p++ = geti (f); break;
case 2: *p++ = to2p (geti (f)); break;
case 3: *p++ = to2p (geti (f));
*p++ = geti (f);
break;
case 4: *p++ = ro2p (geti (f)); break;
}
}
crecp = etypp - geti (f);
p = crecp;
while (p < etypp)
{fp = p;
fp->name = geti (f);
if (fp->name == UNDEF) ++p;
else
{fp->dtype = to2p (geti (f));
fp->offset = geti (f);
p = fp+1;
}
}
cclose (f);
}
type to2p (i) int i;
{extern int typtab[], *etypp;
if (i < 0 || i >= TTSIZE) errx (6006);
return (typtab + i);
}
int *ro2p (i) int i;
{extern int *etypp;
if (i < 0 || i >= TTSIZE) errx (6047);
return (etypp - i);
}
fixstr () {errx (6015);}
errcidn () {errx (6020);}
# ifndef SCRIMP
/**********************************************************************
PRLOC - Print a LOC (for debugging)
**********************************************************************/
prloc (lp) loc *lp;
{int w;
w = lp->word;
switch (lp->flag) {
case l_label: cprint ("LABEL %d", w);
break;
case l_reg: if (w == -1) cprint ("ANY REGISTER");
else cprint ("REGISTERS %o", w);
break;
case l_mem: if (w == -1) cprint ("ANY MEMORY");
else cprint ("MEMORY %o", w);
break;
case l_any: cprint ("ANYWHERE");
break;
default: cprint ("BAD LOC [%d,%d]", lp->flag, w);
}
}
/**********************************************************************
PRTREE - print an enode tree (for debugging)
**********************************************************************/
prtree (ep) enode *ep;
{static int prlev;
int i, op;
econst *ecp;
eidn *eip;
extern int cout;
if (!ep) return;
if ((i = ++prlev) == 1) cputc ('\n', cout);
while (--i >= 0) cputc (' ', cout);
cprint ("%o ", ep);
ecp = eip = ep;
switch (op = ep->op) {
case e_int: cprint ("int %d\n", ecp->eval);
break;
case e_float: cprint ("float %d\n", ecp->eval);
break;
case e_string: cprint ("string %d\n", ecp->eval);
break;
case e_idn: cprint ("idn class=%d, offset=%d, type=",
eip->eclass, eip->eoffset);
typrint (eip->etype, cout);
cprint ("\n");
break;
case e_call: cprint ("[call %o %o] type=",
ep->ep1, ep->ep2);
typrint (ep->etype, cout);
cprint ("\n");
prtree (ep->ep1);
prelist (ep->ep2);
break;
default: cprint ("[%o %o %o] type=",
op, ep->ep1, ep->ep2);
typrint (ep->etype, cout);
cprint ("\n");
prtree (ep->ep1);
prtree (ep->ep2);
}
if (--prlev == 0) cputc ('\n', cout);
}
prelist (np)
int *np;
{if (np[0] != -1) prtree (np);
else
{prelist (np[1]);
prelist (np[2]);
}
}
# endif