From cac4f7ea10a23b7d25a906d56b623e7bafaf8c90 Mon Sep 17 00:00:00 2001 From: Dennis Ritchie Date: Fri, 18 Jul 1975 05:22:07 -0500 Subject: [PATCH] Research V6 development Work on file usr/source/c/cvopt.c Work on file usr/source/c/table.s Work on file usr/source/c/c13.c Work on file usr/source/c/c1t.s Work on file usr/source/c/c10.c Work on file usr/source/c/c1h.c Work on file usr/source/c/c0h.c Work on file usr/source/c/c03.c Work on file usr/source/c/c00.c Work on file usr/source/c/c11.c Work on file usr/source/c/c20.c Work on file usr/source/c/c12.c Work on file usr/source/c/c02.c Work on file usr/source/c/c04.c Work on file usr/source/c/c05.c Work on file usr/source/c/c2h.c Work on file usr/source/c/c21.c Work on file usr/source/c/c01.c Synthesized-from: v6 --- usr/source/c/c00.c | 709 ++++++++++++++++++++++++ usr/source/c/c01.c | 521 ++++++++++++++++++ usr/source/c/c02.c | 673 ++++++++++++++++++++++ usr/source/c/c03.c | 412 ++++++++++++++ usr/source/c/c04.c | 343 ++++++++++++ usr/source/c/c05.c | 176 ++++++ usr/source/c/c0h.c | 351 ++++++++++++ usr/source/c/c10.c | 922 +++++++++++++++++++++++++++++++ usr/source/c/c11.c | 849 ++++++++++++++++++++++++++++ usr/source/c/c12.c | 621 +++++++++++++++++++++ usr/source/c/c13.c | 227 ++++++++ usr/source/c/c1h.c | 272 +++++++++ usr/source/c/c1t.s | 85 +++ usr/source/c/c20.c | 673 ++++++++++++++++++++++ usr/source/c/c21.c | 659 ++++++++++++++++++++++ usr/source/c/c2h.c | 125 +++++ usr/source/c/cvopt.c | 370 +++++++++++++ usr/source/c/table.s | 1255 ++++++++++++++++++++++++++++++++++++++++++ 18 files changed, 9243 insertions(+) create mode 100644 usr/source/c/c00.c create mode 100644 usr/source/c/c01.c create mode 100644 usr/source/c/c02.c create mode 100644 usr/source/c/c03.c create mode 100644 usr/source/c/c04.c create mode 100644 usr/source/c/c05.c create mode 100644 usr/source/c/c0h.c create mode 100644 usr/source/c/c10.c create mode 100644 usr/source/c/c11.c create mode 100644 usr/source/c/c12.c create mode 100644 usr/source/c/c13.c create mode 100644 usr/source/c/c1h.c create mode 100644 usr/source/c/c1t.s create mode 100644 usr/source/c/c20.c create mode 100644 usr/source/c/c21.c create mode 100644 usr/source/c/c2h.c create mode 100644 usr/source/c/cvopt.c create mode 100644 usr/source/c/table.s diff --git a/usr/source/c/c00.c b/usr/source/c/c00.c new file mode 100644 index 0000000000..51720ecbb6 --- /dev/null +++ b/usr/source/c/c00.c @@ -0,0 +1,709 @@ +# +/* C compiler + * + * + * + * Called from cc: + * c0 source temp1 temp2 [ profileflag ] + * temp1 contains some ascii text and the binary expression + * trees. Each tree is introduced by the # character. + * Strings are put on temp2, which cc tacks onto + * temp1 for assembly. + */ + +#include "c0h.c" + +int isn 1; +int stflg 1; +int peeksym -1; +int line 1; +int debug 0; +int dimp 0; +struct tname funcblk { NAME, 0, 0, REG, 0, 0 }; +int *treespace { osspace }; + +struct kwtab { + char *kwname; + int kwval; +} kwtab[] +{ + "int", INT, + "char", CHAR, + "float", FLOAT, + "double", DOUBLE, + "struct", STRUCT, + "long", LONG, + "auto", AUTO, + "extern", EXTERN, + "static", STATIC, + "register", REG, + "goto", GOTO, + "return", RETURN, + "if", IF, + "while", WHILE, + "else", ELSE, + "switch", SWITCH, + "case", CASE, + "break", BREAK, + "continue", CONTIN, + "do", DO, + "default", DEFAULT, + "for", FOR, + "sizeof", SIZEOF, + 0, 0, +}; + +main(argc, argv) +char *argv[]; +{ + extern fin; + register char *sp; + register i; + register struct kwtab *ip; + + if(argc<3) { + error("Arg count"); + exit(1); + } + if((fin=open(argv[1],0))<0) { + error("Can't find %s", argv[1]); + exit(1); + } + if (fcreat(argv[2], obuf)<0 || fcreat(argv[3], sbuf)<0) { + error("Can't create temp"); + exit(1); + } + if (argc>4) + proflg++; + /* + * The hash table locations of the keywords + * are marked; if an identifier hashes to one of + * these locations, it is looked up in in the keyword + * table first. + */ + for (ip=kwtab; (sp = ip->kwname); ip++) { + i = 0; + while (*sp) + i =+ *sp++; + hshtab[i%hshsiz].hflag = FKEYW; + } + while(!eof) { + extdef(); + blkend(); + } + outcode("B", EOF); + strflg++; + outcode("B", EOF); + fflush(obuf); + fflush(sbuf); + exit(nerror!=0); +} + +/* + * Look up the identifier in symbuf in the symbol table. + * If it hashes to the same spot as a keyword, try the keyword table + * first. An initial "." is ignored in the hash. + * Return is a ptr to the symbol table entry. + */ +lookup() +{ + int ihash; + register struct hshtab *rp; + register char *sp, *np; + + ihash = 0; + sp = symbuf; + if (*sp=='.') + sp++; + while (sphflag&FKEYW) + if (findkw()) + return(KEYW); + while (*(np = rp->name)) { + for (sp=symbuf; sp= &hshtab[hshsiz]) + rp = hshtab; + } + if(++hshused >= hshsiz) { + error("Symbol table overflow"); + exit(1); + } + rp->hclass = 0; + rp->htype = 0; + rp->hoffset = 0; + rp->dimp = 0; + rp->hflag =| xdflg; + sp = symbuf; + for (np=rp->name; spkwname); kp++) { + p1 = wp; + while (*p1 == *p2++) + if (*p1++ == '\0') { + cval = kp->kwval; + return(1); + } + } + return(0); +} + + +/* + * Return the next symbol from the input. + * peeksym is a pushed-back symbol, peekc is a pushed-back + * character (after peeksym). + * mosflg means that the next symbol, if an identifier, + * is a member of structure or a structure tag, and it + * gets a "." prepended to it to distinguish + * it from other identifiers. + */ +symbol() { + register c; + register char *sp; + + if (peeksym>=0) { + c = peeksym; + peeksym = -1; + if (c==NAME) + mosflg = 0; + return(c); + } + if (peekc) { + c = peekc; + peekc = 0; + } else + if (eof) + return(EOF); + else + c = getchar(); +loop: + switch(ctab[c]) { + + case INSERT: /* ignore newlines */ + inhdr = 1; + c = getchar(); + goto loop; + + case NEWLN: + if (!inhdr) + line++; + inhdr = 0; + + case SPACE: + c = getchar(); + goto loop; + + case EOF: + eof++; + return(0); + + case PLUS: + return(subseq(c,PLUS,INCBEF)); + + case MINUS: + return(subseq(c,subseq('>',MINUS,ARROW),DECBEF)); + + case ASSIGN: + if (subseq(' ',0,1)) return(ASSIGN); + c = symbol(); + if (c>=PLUS && c<=EXOR) { + if (spnextchar() != ' ' + && (c==MINUS || c==AND || c==TIMES)) { + error("Warning: assignment operator assumed"); + nerror--; + } + return(c+ASPLUS-PLUS); + } + if (c==ASSIGN) + return(EQUAL); + peeksym = c; + return(ASSIGN); + + case LESS: + if (subseq(c,0,1)) return(LSHIFT); + return(subseq('=',LESS,LESSEQ)); + + case GREAT: + if (subseq(c,0,1)) return(RSHIFT); + return(subseq('=',GREAT,GREATEQ)); + + case EXCLA: + return(subseq('=',EXCLA,NEQUAL)); + + case DIVIDE: + if (subseq('*',1,0)) + return(DIVIDE); + while ((c = spnextchar()) != EOF) { + peekc = 0; + if (c=='*') { + if (spnextchar() == '/') { + peekc = 0; + c = getchar(); + goto loop; + } + } + } + eof++; + error("Nonterminated comment"); + return(0); + + case PERIOD: + case DIGIT: + peekc = c; + if ((c=getnum(c=='0'?8:10)) == FCON) + cval = isn++; + return(c); + + case DQUOTE: + return(getstr()); + + case SQUOTE: + return(getcc()); + + case LETTER: + sp = symbuf; + if (mosflg) { + *sp++ = '.'; + mosflg = 0; + } + while(ctab[c]==LETTER || ctab[c]==DIGIT) { + if (sp= 0) { + nchstr++; + if (sp >= &savstr[STRSIZ]) { + sp = savstr; + error("String too long"); + } + *sp++ = c; + } + strptr = sp; + cval = isn++; + return(STRING); +} + +/* + * Write out a string, either in-line + * or in the string temp file labelled by + * lab. + */ +putstr(lab) +{ + register char *sp; + + if (lab) { + strflg++; + outcode("BNB", LABEL, lab, BDATA); + } else + outcode("B", BDATA); + for (sp = savstr; sp= 0) + if(cc++ < NCPW) + *ccp++ = c; + if(cc>NCPW) + error("Long character constant"); + return(CON); +} + +/* + * Read a character in a string or character constant, + * detecting the end of the string. + * It implements the escape sequences. + */ +mapch(ac) +{ + register int a, c, n; + static mpeek; + + c = ac; + if (a = mpeek) + mpeek = 0; + else + a = getchar(); +loop: + if (a==c) + return(-1); + switch(a) { + + case '\n': + case '\0': + error("Nonterminated string"); + peekc = a; + return(-1); + + case '\\': + switch (a=getchar()) { + + case 't': + return('\t'); + + case 'n': + return('\n'); + + case 'b': + return('\b'); + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + n = 0; + c = 0; + while (++c<=3 && '0'<=a && a<='7') { + n =<< 3; + n =+ a-'0'; + a = getchar(); + } + mpeek = a; + return(n); + + case 'r': + return('\r'); + + case '\n': + if (!inhdr) + line++; + inhdr = 0; + a = getchar(); + goto loop; + } + } + return(a); +} + +/* + * Read an expression and return a pointer to its tree. + * It's the classical bottom-up, priority-driven scheme. + * The initflg prevents the parse from going past + * "," or ":" because those delimitesrs are special + * in initializer (and some other) expressions. + */ +tree() +{ +#define SEOF 200 +#define SSIZE 20 + int *op, opst[SSIZE], *pp, prst[SSIZE]; + register int andflg, o; + register struct hshtab *cs; + int p, ps, os; + + space = treespace; + op = opst; + pp = prst; + cp = cmst; + *op = SEOF; + *pp = 06; + andflg = 0; + +advanc: + switch (o=symbol()) { + + case NAME: + cs = csym; + if (cs->hclass==0 && cs->htype==0) + if(nextchar()=='(') { + /* set function */ + cs->hclass = EXTERN; + cs->htype = FUNC; + } else if (initflg) + cs->hclass = EXTERN; + else { + /* set label */ + cs->htype = ARRAY; + if (cs->hoffset==0) + cs->hoffset = isn++; + } + *cp++ = copname(cs); + goto tand; + + case FCON: + if (!initflg) + outcode("BBNB1N1N1N1N0B", DATA,LABEL, + cval, WDATA, fcval, PROG); + + case CON: + case SFCON: + *cp++ = block(1,o,(o==CON?INT:DOUBLE),0,cval); + goto tand; + + /* fake a static char array */ + case STRING: + putstr(cval); + *cp++ = block(3, NAME, ARRAY+CHAR,0,STATIC,0,cval); + +tand: + if(cp>=cmst+cmsiz) { + error("Expression overflow"); + exit(1); + } + if (andflg) + goto syntax; + andflg = 1; + goto advanc; + + case INCBEF: + case DECBEF: + if (andflg) + o =+ 2; + goto oponst; + + case COMPL: + case EXCLA: + case SIZEOF: + if (andflg) + goto syntax; + goto oponst; + + case MINUS: + if (!andflg) { + if ((peeksym=symbol())==FCON) { + fcval = - fcval; + goto advanc; + } + if (peeksym==SFCON) { + fcval = - fcval; + cval =^ 0100000; + goto advanc; + } + o = NEG; + } + andflg = 0; + goto oponst; + + case AND: + case TIMES: + if (andflg) + andflg = 0; else + if(o==AND) + o = AMPER; + else + o = STAR; + goto oponst; + + case LPARN: + if (andflg) { + o = symbol(); + if (o==RPARN) + o = MCALL; + else { + peeksym = o; + o = CALL; + andflg = 0; + } + } + goto oponst; + + case RBRACK: + case RPARN: + if (!andflg) + goto syntax; + goto oponst; + + case DOT: + case ARROW: + mosflg++; + break; + + } + /* binaries */ + if (!andflg) + goto syntax; + andflg = 0; + +oponst: + p = (opdope[o]>>9) & 077; + if ((o==COMMA || o==COLON) && initflg) + p = 05; +opon1: + ps = *pp; + if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) { + switch (o) { + + case INCAFT: + case DECAFT: + p = 37; + break; + case LPARN: + case LBRACK: + case CALL: + p = 04; + } + if (op >= &opst[SSIZE-1]) { + error("expression overflow"); + exit(1); + } + *++op = o; + *++pp = p; + goto advanc; + } + --pp; + switch (os = *op--) { + + case SEOF: + peeksym = o; + build(0); /* flush conversions */ + return(*--cp); + + case CALL: + if (o!=RPARN) + goto syntax; + build(os); + goto advanc; + + case MCALL: + *cp++ = block(0,0,0,0); /* 0 arg call */ + os = CALL; + break; + + case INCBEF: + case INCAFT: + case DECBEF: + case DECAFT: + *cp++ = block(1, CON, INT, 0, 1); + break; + + case LPARN: + if (o!=RPARN) + goto syntax; + goto advanc; + + case LBRACK: + if (o!=RBRACK) + goto syntax; + build(LBRACK); + goto advanc; + } + build(os); + goto opon1; + +syntax: + error("Expression syntax"); + errflush(o); + return(0); +} + +/* + * Generate a tree node for a name. + * All the relevant info from the symbol table is + * copied out, including the name if it's an external. + * This is because the symbol table is gone in the next + * pass, so a ptr isn't sufficient. + */ +copname(acs) +struct hshtab *acs; +{ + register struct hshtab *cs; + register struct tname *tp; + register char *cp1; + int i; + char *cp2; + + cs = acs; + tp = gblock(sizeof(*tp)/NCPW); + tp->op = NAME; + tp->type = cs->htype; + tp->dimp = cs->hdimp; + if ((tp->class = cs->hclass)==0) + tp->class = STATIC; + tp->offset = 0; + tp->nloc = cs->hoffset; + if (cs->hclass==EXTERN) { + gblock((ncps-NCPW)/NCPW); + cp1 = tp->nname; + cp2 = cs->name; + i = ncps; + do { + *cp1++ = *cp2++; + } while (--i); + } + if (cs->hflag&FFIELD) + tp->class = FMOS; + return(tp); +} diff --git a/usr/source/c/c01.c b/usr/source/c/c01.c new file mode 100644 index 0000000000..2b33ad36b1 --- /dev/null +++ b/usr/source/c/c01.c @@ -0,0 +1,521 @@ +# +/* + * C compiler + * + * + */ + +#include "c0h.c" + +/* + * Called from tree, this routine takes the top 1, 2, or 3 + * operands on the expression stack, makes a new node with + * the operator op, and puts it on the stack. + * Essentially all the work is in inserting + * appropriate conversions. + */ +build(op) { + register int t1; + int t2, t3, t; + struct tnode *p3, *disarray(); + register struct tnode *p1, *p2; + int d, dope, leftc, cvn, pcvn; + + /* + * a[i] => *(a+i) + */ + if (op==LBRACK) { + build(PLUS); + op = STAR; + } + dope = opdope[op]; + if ((dope&BINARY)!=0) { + p2 = chkfun(disarray(*--cp)); + t2 = p2->type; + } + p1 = *--cp; + /* + * sizeof gets turned into a number here. + * Bug: sizeof(structure-member-array) is 2 because + * the array has been turned into a ptr already. + */ + if (op==SIZEOF) { + t1 = length(p1); + p1->op = CON; + p1->type = INT; + p1->dimp = 0; + p1->value = t1; + *cp++ = p1; + return; + } + if (op!=AMPER) { + p1 = disarray(p1); + if (op!=CALL) + p1 = chkfun(p1); + } + t1 = p1->type; + pcvn = 0; + t = INT; + switch (op) { + + /* end of expression */ + case 0: + *cp++ = p1; + return; + + /* no-conversion operators */ + case QUEST: + if (p2->op!=COLON) + error("Illegal conditional"); + t = t2; + + case COMMA: + case LOGAND: + case LOGOR: + *cp++ = block(2, op, t, 0, p1, p2); + return; + + case CALL: + if ((t1&XTYPE) != FUNC) + error("Call of non-function"); + *cp++ = block(2,CALL,decref(t1),p1->dimp,p1,p2); + return; + + case STAR: + if (p1->op==AMPER ) { + *cp++ = p1->tr1; + return; + } + if ((t1&XTYPE) == FUNC) + error("Illegal indirection"); + *cp++ = block(1,STAR,decref(t1),p1->dimp,p1); + return; + + case AMPER: + if (p1->op==STAR) { + p1->tr1->dimp = p1->dimp; + p1->tr1->type = incref(t1); + *cp++ = p1->tr1; + return; + } + if (p1->op==NAME) { + *cp++ = block(1,op,incref(t1),p1->dimp,p1); + return; + } + error("Illegal lvalue"); + break; + + /* + * a->b goes to (*a).b + */ + case ARROW: + *cp++ = p1; + chkw(p1, -1); + p1->type = PTR+STRUCT; + build(STAR); + p1 = *--cp; + + /* + * In a.b, a fairly complicated process has to + * be used to make the left operand look + * as if it had the type of the second. + * Also, the offset in the structure has to be + * given a special type to prevent conversion. + */ + case DOT: + if (p2->op!=NAME || (p2->class!=MOS && p2->class!=FMOS)) + error("Illegal structure ref"); + *cp++ = p1; + t = t2; + if ((t&XTYPE) == ARRAY) { + t = decref(t); + p2->ssp++; + } + setype(p1, t, p2->dimp); + build(AMPER); + *cp++ = block(1,CON,NOTYPE,0,p2->nloc); + build(PLUS); + if ((t2&XTYPE) != ARRAY) + build(STAR); + if (p2->class == FMOS) + *cp++ = block(2, FSEL, t, 0, *--cp, p2->dimp); + return; + } + if ((dope&LVALUE)!=0) + chklval(p1); + if ((dope&LWORD)!=0) + chkw(p1, LONG); + if ((dope&RWORD)!=0) + chkw(p2, LONG); + if ((dope&BINARY)==0) { + if (op==ITOF) + t1 = DOUBLE; + else if (op==FTOI) + t1 = INT; + if (!fold(op, p1, 0)) + *cp++ = block(1,op,t1,p1->dimp,p1); + return; + } + cvn = 0; + if (t1==STRUCT || t2==STRUCT) { + error("Unimplemented structure operation"); + t1 = t2 = INT; + } + if (t2==NOTYPE) { + t = t1; + p2->type = INT; /* no int cv for struct */ + t2 = INT; + } else + cvn = cvtab[lintyp(t1)][lintyp(t2)]; + leftc = (cvn>>4)&017; + cvn =& 017; + t = leftc? t2:t1; + if (dope&ASSGOP) { + t = t1; + if (op==ASSIGN && (cvn==ITP||cvn==PTI)) + cvn = leftc = 0; + if (leftc) + cvn = leftc; + leftc = 0; + } else if (op==COLON && t1>=PTR && t1==t2) + cvn = 0; + else if (dope&RELAT) { + if (op>=LESSEQ && (t1>=PTR || t2>=PTR)) + op =+ LESSEQP-LESSEQ; + if (cvn==PTI) + cvn = 0; + } + if (cvn==PTI) { + cvn = 0; + if (op==MINUS) { + t = INT; + pcvn++; + } else { + if (t1!=t2 || t1!=(PTR+CHAR)) + cvn = XX; + } + } + if (cvn) { + t1 = plength(p1); + t2 = plength(p2); + if (cvn==XX || (cvn==PTI&&t1!=t2)) + error("Illegal conversion"); + else if (leftc) + p1 = convert(p1, t, cvn, t2); + else + p2 = convert(p2, t, cvn, t1); + } + if (dope&RELAT) + t = INT; + if (fold(op, p1, p2)==0) + *cp++ = block(2,op,t,(p1->dimp==0? p2:p1)->dimp,p1,p2); + if (pcvn && t1!=(PTR+CHAR)) { + p1 = *--cp; + *cp++ = convert(p1, 0, PTI, plength(p1->tr1)); + } +} + +/* + * Generate the appropirate conversion operator. + * For pointer <=> integer this is a multiplication + * or division, otherwise a special operator. + */ +convert(p, t, cvn, len) +struct tnode *p; +{ + register int n; + + switch(cvn) { + + case PTI: + case ITP: + if (len==1) + return(p); + return(block(2, (cvn==PTI?DIVIDE:TIMES), t, 0, p, + block(1, CON, 0, 0, len))); + + case ITF: + n = ITOF; + break; + case FTI: + n = FTOI; + break; + case ITL: + n = ITOL; + break; + case LTI: + n = LTOI; + break; + case FTL: + n = FTOL; + break; + case LTF: + n = LTOF; + break; + } + return(block(1, n, t, 0, p)); +} + +/* + * Traverse an expression tree, adjust things + * so the types of things in it are consistent + * with the view that its top node has + * type at. + * Used with structure references. + */ +setype(ap, at, adimptr) +struct tnode *ap; +{ + register struct tnode *p; + register t, dimptr; + + p = ap; + t = at; + dimptr = adimptr; + p->type = t; + if (dimptr != -1) + p->dimp = dimptr; + switch(p->op) { + + case AMPER: + setype(p->tr1, decref(t), dimptr); + return; + + case STAR: + setype(p->tr1, incref(t), dimptr); + return; + + case PLUS: + case MINUS: + setype(p->tr1, t, dimptr); + } +} + +/* + * A mention of a function name is turned into + * a pointer to that function. + */ +chkfun(ap) +struct tnode *ap; +{ + register struct tnode *p; + register int t; + + p = ap; + if (((t = p->type)&XTYPE)==FUNC) + return(block(1,AMPER,incref(t),p->dimp,p)); + return(p); +} + +/* + * A mention of an array is turned into + * a pointer to the base of the array. + */ +struct tnode *disarray(ap) +struct tnode *ap; +{ + register int t; + register struct tnode *p; + + p = ap; + /* check array & not MOS */ + if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->class==MOS) + return(p); + p->ssp++; + *cp++ = p; + setype(p, decref(t), -1); + build(AMPER); + return(*--cp); +} + +/* + * make sure that p is a ptr to a node + * with type int or char or 'okt.' + * okt might be nonexistent or 'long' + * (e.g. for <<). + */ +chkw(p, okt) +struct tnode *p; +{ + register int t; + + if ((t=p->type)>CHAR && t= &osspace[OSSIZ]) { + error("Expression overflow"); + exit(1); + } + return(p); +} + +/* + * Check that a tree can be used as an lvalue. + */ +chklval(ap) +struct tnode *ap; +{ + register struct tnode *p; + + p = ap; + if (p->op!=NAME && p->op!=STAR) + error("Lvalue required"); +} + +/* + * reduce some forms of `constant op constant' + * to a constant. More of this is done in the next pass + * but this is used to allow constant expressions + * to be used in switches and array bounds. + */ +fold(op, ap1, ap2) +struct tnode *ap1, *ap2; +{ + register struct tnode *p1; + register int v1, v2; + + p1 = ap1; + if (p1->op!=CON || (ap2!=0 && ap2->op!=CON)) + return(0); + v1 = p1->value; + v2 = ap2->value; + switch (op) { + + case PLUS: + v1 =+ v2; + break; + + case MINUS: + v1 =- v2; + break; + + case TIMES: + v1 =* v2; + break; + + case DIVIDE: + v1 =/ v2; + break; + + case MOD: + v1 =% v2; + break; + + case AND: + v1 =& v2; + break; + + case OR: + v1 =| v2; + break; + + case EXOR: + v1 =^ v2; + break; + + case NEG: + v1 = - v1; + break; + + case COMPL: + v1 = ~ v1; + break; + + case LSHIFT: + v1 =<< v2; + break; + + case RSHIFT: + v1 =>> v2; + break; + + default: + return(0); + } + p1->value = v1; + *cp++ = p1; + return(1); +} + +/* + * Compile an expression expected to have constant value, + * for example an array bound or a case value. + */ +conexp() +{ + register struct tnode *t; + + initflg++; + if (t = tree()) + if (t->op != CON) + error("Constant required"); + initflg--; + return(t->value); +} diff --git a/usr/source/c/c02.c b/usr/source/c/c02.c new file mode 100644 index 0000000000..1a37702474 --- /dev/null +++ b/usr/source/c/c02.c @@ -0,0 +1,673 @@ +# +/* C compiler + * + * + */ + +#include "c0h.c" + +/* + * Process a single external definition + */ +extdef() +{ + register o, elsize; + int type, sclass; + register struct hshtab *ds; + + if(((o=symbol())==EOF) || o==SEMI) + return; + peeksym = o; + type = INT; + sclass = EXTERN; + xdflg = FNDEL; + if ((elsize = getkeywords(&sclass, &type)) == -1 && peeksym!=NAME) + goto syntax; + if (type==STRUCT) + blkhed(); + do { + defsym = 0; + decl1(EXTERN, type, 0, elsize); + if ((ds=defsym)==0) + return; + funcsym = ds; + ds->hflag =| FNDEL; + outcode("BS", SYMDEF, ds->name); + xdflg = 0; + if ((ds->type&XTYPE)==FUNC) { + if ((peeksym=symbol())==LBRACE || peeksym==KEYW) { + funcblk.type = decref(ds->type); + cfunc(ds->name); + return; + } + } else + cinit(ds); + } while ((o=symbol())==COMMA); + if (o==SEMI) + return; +syntax: + if (o==RBRACE) { + error("Too many }'s"); + peeksym = 0; + return; + } + error("External definition syntax"); + errflush(o); + statement(0); +} + +/* + * Process a function definition. + */ +cfunc(cs) +char *cs; +{ + register savdimp; + + savdimp = dimp; + outcode("BBS", PROG, RLABEL, cs); + declist(ARG); + regvar = 5; + retlab = isn++; + if ((peeksym = symbol()) != LBRACE) + error("Compound statement required"); + statement(1); + outcode("BNB", LABEL, retlab, RETRN); + dimp = savdimp; +} + +/* + * Process the initializers for an external definition. + */ +cinit(ds) +struct hshtab *ds; +{ + register basetype, nel, ninit; + int o, width, realwidth; + + nel = 1; + basetype = ds->type; + /* + * If it's an array, find the number of elements. + * "basetype" is the type of thing it's an array of. + */ + while ((basetype&XTYPE)==ARRAY) { + if ((nel = dimtab[ds->ssp&0377])==0) + nel = 1; + basetype = decref(basetype); + } + realwidth = width = length(ds) / nel; + /* + * Pretend a structure is kind of an array of integers. + * This is a kludge. + */ + if (basetype==STRUCT) { + nel =* realwidth/2; + width = 2; + } + if ((peeksym=symbol())==COMMA || peeksym==SEMI) { + outcode("BSN",CSPACE,ds->name,(nel*width+ALIGN)&~ALIGN); + return; + } + ninit = 0; + outcode("BBS", DATA, NLABEL, ds->name); + if ((o=symbol())==LBRACE) { + do + ninit = cinit1(ds, basetype, width, ninit, nel); + while ((o=symbol())==COMMA); + if (o!=RBRACE) + peeksym = o; + } else { + peeksym = o; + ninit = cinit1(ds, basetype, width, 0, nel); + } + /* + * Above we pretended that a structure was a bunch of integers. + * Readjust in accordance with reality. + * First round up partial initializations. + */ + if (basetype==STRUCT) { + if (o = 2*ninit % realwidth) + outcode("BN", SSPACE, realwidth-o); + ninit = (2*ninit+realwidth-2) / realwidth; + nel =/ realwidth/2; + } + /* + * If there are too few initializers, allocate + * more storage. + * If there are too many initializers, extend + * the declared size for benefit of "sizeof" + */ + if (ninitnel) { + if ((ds->type&XTYPE)==ARRAY) + dimtab[ds->ssp&0377] = ninit; + nel = ninit; + } + /* + * If it's not an array, only one initializer is allowed. + */ + if (ninit>1 && (ds->type&XTYPE)!=ARRAY) + error("Too many initializers"); + if (((nel&width)&ALIGN)) + outcode("B", EVEN); +} + +/* + * Process a single expression in a sequence of initializers + * for an external. Mainly, it's for checking + * type compatibility. + */ +cinit1(ds, type, awidth, aninit, nel) +struct hshtab *ds; +{ + float sf; + register struct tnode *s; + register width, ninit; + + width = awidth; + ninit = aninit; + if ((peeksym=symbol())==STRING && type==CHAR) { + peeksym = -1; + if (ninit) + bxdec(); + putstr(0); + if (nel>nchstr) { + strflg++; + outcode("BN", SSPACE, nel-nchstr); + strflg = 0; + nchstr = nel; + } + return(nchstr); + } + if (peeksym==RBRACE) + return(ninit); + initflg++; + s = tree(); + initflg = 0; + switch(width) { + + case 1: + if (s->op != CON) + goto bad; + outcode("B1N0", BDATA, s->value); + break; + + case 2: + if (s->op==CON) { + outcode("B1N0", WDATA, s->value); + break; + } + if (s->op==FCON || s->op==SFCON) { + if (type==STRUCT) { + ninit =+ 3; + goto prflt; + } + goto bad; + } + rcexpr(block(1,INIT,0,0,s)); + break; + + case 4: + sf = fcval; + outcode("B1N1N0", WDATA, sf); + goto flt; + + case 8: + prflt: + outcode("B1N1N1N1N0", WDATA, fcval); + flt: + if (s->op==FCON || s->op==SFCON) + break; + + default: + bad: + bxdec(); + + } + return(++ninit); +} + +bxdec() +{ + error("Inconsistent external initialization"); +} + +/* + * Process one statement in a function. + */ +statement(d) +{ + register o, o1, o2; + int o3, o4; + struct tnode *np; + +stmt: + switch(o=symbol()) { + + case EOF: + error("Unexpected EOF"); + case SEMI: + return; + + case LBRACE: + if (d) { + if (proflg) + outcode("BN", PROFIL, isn++); + outcode("BN", SAVE, blkhed()); + } + while (!eof) { + if ((o=symbol())==RBRACE) + return; + peeksym = o; + statement(0); + } + error("Missing '}'"); + return; + + case KEYW: + switch(cval) { + + case GOTO: + if (o1 = simplegoto()) + branch(o1); + else + dogoto(); + goto semi; + + case RETURN: + doret(); + goto semi; + + case IF: + np = pexpr(); + o2 = 0; + if ((o1=symbol())==KEYW) switch (cval) { + case GOTO: + if (o2=simplegoto()) + goto simpif; + cbranch(np, o2=isn++, 0); + dogoto(); + label(o2); + goto hardif; + + case RETURN: + if (nextchar()==';') { + o2 = retlab; + goto simpif; + } + cbranch(np, o1=isn++, 0); + doret(); + label(o1); + o2++; + goto hardif; + + case BREAK: + o2 = brklab; + goto simpif; + + case CONTIN: + o2 = contlab; + simpif: + chconbrk(o2); + cbranch(np, o2, 1); + hardif: + if ((o=symbol())!=SEMI) + goto syntax; + if ((o1=symbol())==KEYW && cval==ELSE) + goto stmt; + peeksym = o1; + return; + } + peeksym = o1; + cbranch(np, o1=isn++, 0); + statement(0); + if ((o=symbol())==KEYW && cval==ELSE) { + o2 = isn++; + branch(o2); + label(o1); + statement(0); + label(o2); + return; + } + peeksym = o; + label(o1); + return; + + case WHILE: + o1 = contlab; + o2 = brklab; + label(contlab = isn++); + cbranch(pexpr(), brklab=isn++, 0); + statement(0); + branch(contlab); + label(brklab); + contlab = o1; + brklab = o2; + return; + + case BREAK: + chconbrk(brklab); + branch(brklab); + goto semi; + + case CONTIN: + chconbrk(contlab); + branch(contlab); + goto semi; + + case DO: + o1 = contlab; + o2 = brklab; + contlab = isn++; + brklab = isn++; + label(o3 = isn++); + statement(0); + label(contlab); + contlab = o1; + if ((o=symbol())==KEYW && cval==WHILE) { + cbranch(tree(), o3, 1); + label(brklab); + brklab = o2; + goto semi; + } + goto syntax; + + case CASE: + o1 = conexp(); + if ((o=symbol())!=COLON) + goto syntax; + if (swp==0) { + error("Case not in switch"); + goto stmt; + } + if(swp>=swtab+swsiz) { + error("Switch table overflow"); + } else { + swp->swlab = isn; + (swp++)->swval = o1; + label(isn++); + } + goto stmt; + + case SWITCH: + o1 = brklab; + brklab = isn++; + np = pexpr(); + chkw(np, -1); + rcexpr(block(1,RFORCE,0,0,np)); + pswitch(); + brklab = o1; + return; + + case DEFAULT: + if (swp==0) + error("Default not in switch"); + if ((o=symbol())!=COLON) + goto syntax; + label(deflab = isn++); + goto stmt; + + case FOR: + o1 = contlab; + o2 = brklab; + contlab = isn++; + brklab = isn++; + if (o=forstmt()) + goto syntax; + label(brklab); + contlab = o1; + brklab = o2; + return; + } + + error("Unknown keyword"); + goto syntax; + + case NAME: + if (nextchar()==':') { + peekc = 0; + o1 = csym; + if (o1->hclass>0) { + error("Redefinition"); + goto stmt; + } + o1->hclass = STATIC; + o1->htype = ARRAY; + if (o1->hoffset==0) + o1->hoffset = isn++; + label(o1->hoffset); + goto stmt; + } + } + peeksym = o; + rcexpr(tree()); + +semi: + if ((o=symbol())==SEMI) + return; +syntax: + error("Statement syntax"); + errflush(o); +} + +/* + * Process a for statement. + */ +forstmt() +{ + register int l, o, sline; + int sline1, *ss; + struct tnode *st; + + if ((o=symbol()) != LPARN) + return(o); + if ((o=symbol()) != SEMI) { /* init part */ + peeksym = o; + rcexpr(tree()); + if ((o=symbol()) != SEMI) + return(o); + } + label(contlab); + if ((o=symbol()) != SEMI) { /* test part */ + peeksym = o; + rcexpr(block(1,CBRANCH,tree(),brklab,0)); + if ((o=symbol()) != SEMI) + return(o); + } + if ((peeksym=symbol()) == RPARN) { /* incr part */ + peeksym = -1; + statement(0); + branch(contlab); + return(0); + } + l = contlab; + contlab = isn++; + st = tree(); + sline = line; + if ((o=symbol()) != RPARN) + return(o); + ss = treespace; + treespace = space; + statement(0); + sline1 = line; + line = sline; + label(contlab); + rcexpr(st); + line = sline1; + treespace = ss; + branch(l); + return(0); +} + +/* + * A parenthesized expression, + * as after "if". + */ +pexpr() +{ + register o, t; + + if ((o=symbol())!=LPARN) + goto syntax; + t = tree(); + if ((o=symbol())!=RPARN) + goto syntax; + return(t); +syntax: + error("Statement syntax"); + errflush(o); + return(0); +} + +/* + * The switch stateent, which involves collecting the + * constants and labels for the cases. + */ +pswitch() +{ + register struct swtab *cswp, *sswp; + int dl, swlab; + + cswp = sswp = swp; + if (swp==0) + cswp = swp = swtab; + branch(swlab=isn++); + dl = deflab; + deflab = 0; + statement(0); + branch(brklab); + label(swlab); + if (deflab==0) + deflab = brklab; + outcode("BNN", SWIT, deflab, line); + for (; cswp < swp; cswp++) + outcode("NN", cswp->swlab, cswp->swval); + outcode("0"); + label(brklab); + deflab = dl; + swp = sswp; +} + +/* + * blkhed is called at the start of each function. + * It reads the declarations at the start; + * then assigns storage locations for the + * parameters (which have been linked into a list, + * in order of appearance). + * This list is necessary because in + * f(a, b) float b; int a; ... + * the names are seen before the types. + * Also, the routine adjusts structures involved + * in some kind of forward-referencing. + */ +blkhed() +{ + register pl; + register struct hshtab *cs; + + autolen = 6; + declist(0); + pl = 4; + while(paraml) { + parame->hoffset = 0; + cs = paraml; + paraml = paraml->hoffset; + if (cs->htype==FLOAT) + cs->htype = DOUBLE; + cs->hoffset = pl; + cs->hclass = AUTO; + if ((cs->htype&XTYPE) == ARRAY) { + cs->htype =- (ARRAY-PTR); /* set ptr */ + cs->ssp++; /* pop dims */ + } + pl =+ rlength(cs); + } + for (cs=hshtab; csname[0] == '\0') + continue; + /* check tagged structure */ + if (cs->hclass>KEYWC && (cs->htype&TYPE)==RSTRUCT) { + cs->lenp = dimtab[cs->lenp&0377]->lenp; + cs->htype = cs->htype&~TYPE | STRUCT; + } + if (cs->hclass == STRTAG && dimtab[cs->lenp&0377]==0) + error("Undefined structure: %.8s", cs->name); + if (cs->hclass == ARG) + error("Not an argument: %.8s", cs->name); + if (stflg) + prste(cs); + } + space = treespace; + outcode("BN", SETREG, regvar); + return(autolen); +} + +/* + * After a function definition, delete local + * symbols. + * Also complain about undefineds. + */ +blkend() { + register struct hshtab *cs; + + for (cs=hshtab; csname[0]) { + if (cs->hclass==0 && (cs->hflag&FNUND)==0) { + error("%.8s undefined", cs->name); + cs->hflag =| FNUND; + } + if((cs->hflag&FNDEL)==0) { + cs->name[0] = '\0'; + hshused--; + cs->hflag =& ~(FNUND|FFIELD); + } + } + } +} + +/* + * write out special definitions of local symbols for + * benefit of the debugger. None of these are used + * by the assembler except to save them. + */ +prste(acs) +{ + register struct hshtab *cs; + register nkind; + + cs = acs; + switch (cs->hclass) { + case REG: + nkind = RNAME; + break; + + case AUTO: + nkind = ANAME; + break; + + case STATIC: + nkind = SNAME; + break; + + default: + return; + + } + outcode("BSN", nkind, cs->name, cs->hoffset); +} + +/* + * In case of error, skip to the next + * statement delimiter. + */ +errflush(ao) +{ + register o; + + o = ao; + while(o>RBRACE) /* ; { } */ + o = symbol(); + peeksym = o; +} diff --git a/usr/source/c/c03.c b/usr/source/c/c03.c new file mode 100644 index 0000000000..3c72ae0feb --- /dev/null +++ b/usr/source/c/c03.c @@ -0,0 +1,412 @@ +# +/* + * C compiler, phase 1 + * + * + * Handles processing of declarations, + * except for top-level processing of + * externals. + */ + +#include "c0h.c" + +/* + * Process a sequence of declaration statements + */ +declist(sclass) +{ + register sc, elsize, offset; + int type; + + offset = 0; + sc = sclass; + while ((elsize = getkeywords(&sclass, &type)) != -1) { + offset = declare(sclass, type, offset, elsize); + sclass = sc; + } + return(offset+align(INT, offset, 0)); +} + +/* + * Read the keywords introducing a declaration statement + */ +getkeywords(scptr, tptr) +int *scptr, *tptr; +{ + register skw, tkw, longf; + int o, elsize, isadecl, ismos; + + isadecl = 0; + longf = 0; + tkw = -1; + skw = *scptr; + elsize = 0; + ismos = skw==MOS; + for (;;) { + mosflg = ismos; + switch ((o=symbol())==KEYW? cval: -1) { + + case AUTO: + case STATIC: + case EXTERN: + case REG: + if (skw && skw!=cval) + error("Conflict in storage class"); + skw = cval; + break; + + case LONG: + longf++; + break; + + case STRUCT: + o = STRUCT; + elsize = strdec(&o, ismos); + cval = o; + case INT: + case CHAR: + case FLOAT: + case DOUBLE: + if (tkw>=0) + error("Type clash"); + tkw = cval; + break; + + default: + peeksym = o; + if (isadecl==0) + return(-1); + if (tkw<0) + tkw = INT; + if (skw==0) + skw = AUTO; + if (longf) { + if (tkw==FLOAT) + tkw = DOUBLE; + else if (tkw==INT) + tkw = LONG; + else + error("Misplaced 'long'"); + } + *scptr = skw; + *tptr = tkw; + return(elsize); + } + isadecl++; + } +} + +/* + * Process a structure declaration; a subroutine + * of getkeywords. + */ +strdec(tkwp, mosf) +int *tkwp; +{ + register elsize, o; + register struct hshtab *ssym; + int savebits; + struct hshtab *ds; + + mosflg = 1; + ssym = 0; + if ((o=symbol())==NAME) { + ssym = csym; + if (ssym->hclass==0) { + ssym->hclass = STRTAG; + ssym->lenp = dimp; + chkdim(); + dimtab[dimp++] = 0; + } + if (ssym->hclass != STRTAG) + redec(); + mosflg = mosf; + o = symbol(); + } + mosflg = 0; + if (o != LBRACE) { + if (ssym==0) { + syntax: + decsyn(o); + return(0); + } + if (ssym->hclass!=STRTAG) + error("Bad structure name"); + if ((elsize = dimtab[ssym->lenp&0377])==0) { + *tkwp = RSTRUCT; + elsize = ssym; + } + peeksym = o; + } else { + ds = defsym; + mosflg = 0; + savebits = bitoffs; + bitoffs = 0; + elsize = declist(MOS); + bitoffs = savebits; + defsym = ds; + if ((o = symbol()) != RBRACE) + goto syntax; + if (ssym) { + if (dimtab[ssym->lenp&0377]) + error("%.8s redeclared", ssym->name); + dimtab[ssym->lenp&0377] = elsize; + } + } + return(elsize); +} + +/* + * Check that the dimension table has not overflowed + */ +chkdim() +{ + if (dimp >= dimsiz) { + error("Dimension/struct table overflow"); + exit(1); + } +} + +/* + * Process a comma-separated list of declarators + */ +declare(askw, tkw, offset, elsize) +{ + register int o; + register int skw; + + skw = askw; + do { + offset =+ decl1(skw, tkw, offset, elsize); + } while ((o=symbol()) == COMMA); + if (o==SEMI || o==RPARN && skw==ARG1) + return(offset); + decsyn(o); +} + +/* + * Process a single declarator + */ +decl1(askw, tkw, offset, elsize) +{ + int t1, chkoff, a; + register int type, skw; + register struct hshtab *dsym; + + skw = askw; + chkoff = 0; + mosflg = skw==MOS; + if ((peeksym=symbol())==SEMI || peeksym==RPARN) + return(0); + /* + * Filler field + */ + if (peeksym==COLON && skw==MOS) { + peeksym = -1; + t1 = conexp(); + elsize = align(tkw, offset, t1); + bitoffs =+ t1; + return(elsize); + } + if ((t1=getype()) < 0) + goto syntax; + type = 0; + do + type = type<>TYLEN) & XTYPE)!=0); + type =| tkw; + dsym = defsym; + if (!(dsym->hclass==0 + || (skw==ARG && dsym->hclass==ARG1) + || (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type))) + if (skw==MOS && dsym->hclass==MOS && dsym->htype==type) + chkoff = 1; + else { + redec(); + goto syntax; + } + dsym->htype = type; + if (skw) + dsym->hclass = skw; + if (skw==ARG1) { + if (paraml==0) + paraml = dsym; + else + parame->hoffset = dsym; + parame = dsym; + } + if (elsize && ((type&TYPE)==RSTRUCT || (type&TYPE)==STRUCT)) { + dsym->lenp = dimp; + chkdim(); + dimtab[dimp++] = elsize; + } + elsize = 0; + if (skw==MOS) { + elsize = length(dsym); + t1 = 0; + if ((peeksym = symbol())==COLON) { + elsize = 0; + peeksym = -1; + t1 = conexp(); + dsym->hflag =| FFIELD; + } + a = align(type, offset, t1); + elsize =+ a; + offset =+ a; + if (t1) { + if (chkoff && (dsym->bitoffs!=bitoffs + || dsym->flen!=t1)) + redec(); + dsym->bitoffs = bitoffs; + dsym->flen = t1; + bitoffs =+ t1; + } + if (chkoff && dsym->hoffset != offset) + redec(); + dsym->hoffset = offset; + } + if ((dsym->htype&XTYPE)==FUNC) { + if (dsym->hclass!=EXTERN && dsym->hclass!=AUTO) + error("Bad function"); + dsym->hclass = EXTERN; + } + if (dsym->hclass==AUTO) { + autolen =+ rlength(dsym); + dsym->hoffset = -autolen; + } else if (dsym->hclass==STATIC) { + dsym->hoffset = isn; + outcode("BBNBNB", BSS, LABEL, isn++, + SSPACE, rlength(dsym), PROG); + } else if (dsym->hclass==REG) { + if ((type&TYPE)>CHAR && (type&XTYPE)==0 + || (type&XTYPE)>PTR || regvar<3) + error("Bad register %o", type); + dsym->hoffset = --regvar; + } +syntax: + return(elsize); +} + +/* + * Read a declarator and get the implied type + */ +getype() +{ + register int o, type; + register struct hshtab *ds; + + switch(o=symbol()) { + + case TIMES: + return(getype()<ssp = dimp; + getf: + switch(o=symbol()) { + + case LPARN: + if (xdflg) { + xdflg = 0; + ds = defsym; + declare(ARG1, 0, 0, 0); + defsym = ds; + xdflg++; + } else + if ((o=symbol()) != RPARN) + goto syntax; + type = type<ssp&0377; ooffset) + bitoffs = 0; + } + if (flen) { + if (type==INT) { + if (flen > NBPW) + error(ftl); + if (flen+bitoffs > NBPW) { + bitoffs = 0; + a =+ NCPW; + } + } else if (type==CHAR) { + if (flen > NBPC) + error(ftl); + if (flen+bitoffs > NCPW) { + bitoffs = 0; + a =+ 1; + } + } else + error("Bad type for field"); + } + return(a-offset); +} + +/* + * Complain about syntax error in declaration + */ +decsyn(o) +{ + error("Declaration syntax"); + errflush(o); +} + +/* + * Complain about a redeclaration + */ +redec() +{ + error("%.8s redeclared", defsym->name); +} diff --git a/usr/source/c/c04.c b/usr/source/c/c04.c new file mode 100644 index 0000000000..064aed4695 --- /dev/null +++ b/usr/source/c/c04.c @@ -0,0 +1,343 @@ +# +/* + * C compiler + * + * + */ + +#include "c0h.c" + +/* + * Reduce the degree-of-reference by one. + * e.g. turn "ptr-to-int" into "int". + */ +decref(at) +{ + register t; + + t = at; + if ((t & ~TYPE) == 0) { + error("Illegal indirection"); + return(t); + } + return((t>>TYLEN) & ~TYPE | t&TYPE); +} + +/* + * Increase the degree of reference by + * one; e.g. turn "int" to "ptr-to-int". + */ +incref(t) +{ + return(((t&~TYPE)<op) { + + case 0: + outcode("B", NULL); + return; + + case NAME: + outcode("BNN", NAME, tree->class, tree->type); + if (tree->class==EXTERN) + outcode("S", tree->nname); + else + outcode("N", tree->nloc); + return; + + case CON: + case FCON: + case SFCON: + outcode("BNN", tree->op, tree->type, tree->value); + return; + + case FSEL: + treeout(tree->tr1); + outcode("BNN", tree->op, tree->type, tree->tr2); + return; + + case CBRANCH: + treeout(tree->btree); + outcode("BNN", tree->op, tree->lbl, tree->cond); + return; + + default: + treeout(tree->tr1); + if (opdope[tree->op]&BINARY) + treeout(tree->tr2); + outcode("BN", tree->op, tree->type); + return; + } +} + +/* + * Generate a branch + */ +branch(lab) { + outcode("BN", BRANCH, lab); +} + +/* + * Generate a label + */ +label(l) { + outcode("BN", LABEL, l); +} + +/* + * ap is a tree node whose type + * is some kind of pointer; return the size of the object + * to which the pointer points. + */ +plength(ap) +struct tname *ap; +{ + register t, l; + register struct tname *p; + + p = ap; + if (p==0 || ((t=p->type)&~TYPE) == 0) /* not a reference */ + return(1); + p->type = decref(t); + l = length(p); + p->type = t; + return(l); +} + +/* + * return the number of bytes in the object + * whose tree node is acs. + */ +length(acs) +struct tnode *acs; +{ + register t, n; + register struct tnode *cs; + + cs = acs; + t = cs->type; + n = 1; + while ((t&XTYPE) == ARRAY) { + t = decref(t); + n = dimtab[cs->ssp&0377]; + } + if ((t&~TYPE)==FUNC) + return(0); + if (t>=PTR) + return(2*n); + switch(t&TYPE) { + + case INT: + return(2*n); + + case CHAR: + return(n); + + case FLOAT: + case LONG: + return(4*n); + + case DOUBLE: + return(8*n); + + case STRUCT: + return(n * dimtab[cs->lenp&0377]); + + case RSTRUCT: + error("Bad structure"); + return(0); + } + error("Compiler error (length)"); +} + +/* + * The number of bytes in an object, rounded up to a word. + */ +rlength(cs) +struct tnode *cs; +{ + return((length(cs)+ALIGN) & ~ALIGN); +} + +/* + * After an "if (...) goto", look to see if the transfer + * is to a simple label. + */ +simplegoto() +{ + register struct hshtab *csp; + + if ((peeksym=symbol())==NAME && nextchar()==';') { + csp = csym; + if (csp->hclass==0 && csp->htype==0) { + csp->htype = ARRAY; + if (csp->hoffset==0) + csp->hoffset = isn++; + } + if ((csp->hclass==0||csp->hclass==STATIC) + && csp->htype==ARRAY) { + peeksym = -1; + return(csp->hoffset); + } + } + return(0); +} + +/* + * Return the next non-white-space character + */ +nextchar() +{ + while (spnextchar()==' ') + peekc = 0; + return(peekc); +} + +/* + * Return the next character, translating all white space + * to blank and handling line-ends. + */ +spnextchar() +{ + register c; + + if ((c = peekc)==0) + c = getchar(); + if (c=='\t') + c = ' '; + else if (c=='\n') { + c = ' '; + if (inhdr==0) + line++; + inhdr = 0; + } else if (c=='\001') { /* SOH, insert marker */ + inhdr++; + c = ' '; + } + peekc = c; + return(c); +} + +/* + * is a break or continue legal? + */ +chconbrk(l) +{ + if (l==0) + error("Break/continue error"); +} + +/* + * The goto statement. + */ +dogoto() +{ + register struct tnode *np; + + *cp++ = tree(); + build(STAR); + chkw(np = *--cp, -1); + rcexpr(block(1,JUMP,0,0,np)); +} + +/* + * The return statement, which has to convert + * the returned object to the function's type. + */ +doret() +{ + register struct tnode *t; + + if (nextchar() != ';') { + t = tree(); + *cp++ = &funcblk; + *cp++ = t; + build(ASSIGN); + cp[-1] = cp[-1]->tr2; + build(RFORCE); + rcexpr(*--cp); + } + branch(retlab); +} + +/* + * write out a character to the usual output + * or to the string file + */ +putchar(c) +{ + write(1, &c, 1); +} + +outcode(s, a) +char *s; +{ + register char *sp; + register *ap, *bufp; + int n; + char *np; + + bufp = obuf; + if (strflg) + bufp = sbuf; + ap = &a; + for (;;) switch(*s++) { + case 'B': + putw(*ap++ | (0376<<8), bufp); + continue; + + case 'N': + putw(*ap++, bufp); + continue; + + case 'S': + np = *ap++; + n = ncps; + while (n-- && *np) { + putc(*np++, bufp); + } + putc(0, bufp); + continue; + + case '1': + putw(1, bufp); + continue; + + case '0': + putw(0, bufp); + continue; + + case '\0': + return; + } + error("Botch in outcode"); +} diff --git a/usr/source/c/c05.c b/usr/source/c/c05.c new file mode 100644 index 0000000000..3dbad30315 --- /dev/null +++ b/usr/source/c/c05.c @@ -0,0 +1,176 @@ +# +#include "c0h.c" +/* + * info on operators: + * 01-- is binary operator + * 02-- left (or only) operand must be lvalue + * 04-- is relational operator + * 010-- is assignment-type operator + * 020-- non-float req. on left + * 040-- non-float req. on right + * 0100-- is commutative + * 0200-- is right, not left-associative + * 0400-- is leaf of tree + * *0XX000-- XX is priority of operator + */ +int opdope[] { + 000000, /* EOF */ + 000000, /* ; */ + 000000, /* { */ + 000000, /* } */ + 036000, /* [ */ + 002000, /* ] */ + 036000, /* ( */ + 002000, /* ) */ + 014201, /* : */ + 007001, /* , */ + 000000, /* field selection */ + 000000, /* 11 */ + 000000, /* 12 */ + 000000, /* 13 */ + 000000, /* 14 */ + 000000, /* 15 */ + 000000, /* 16 */ + 000000, /* 17 */ + 000000, /* 18 */ + 000000, /* 19 */ + 000400, /* name */ + 000400, /* short constant */ + 000400, /* string */ + 000400, /* float */ + 000400, /* double */ + 000000, /* 25 */ + 000000, /* 26 */ + 000000, /* 27 */ + 000000, /* 28 */ + 000000, /* 29 */ + 034203, /* ++pre */ + 034203, /* --pre */ + 034203, /* ++post */ + 034203, /* --post */ + 034220, /* !un */ + 034202, /* &un */ + 034220, /* *un */ + 034200, /* -un */ + 034220, /* ~un */ + 036001, /* . (structure reference) */ + 030101, /* + */ + 030001, /* - */ + 032101, /* * */ + 032001, /* / */ + 032001, /* % */ + 026061, /* >> */ + 026061, /* << */ + 020161, /* & */ + 017161, /* | */ + 017161, /* ^ */ + 036001, /* -> */ + 000000, /* int -> double */ + 000000, /* double -> int */ + 016001, /* && */ + 015001, /* || */ + 030001, /* &~ */ + 000000, /* 56 */ + 000000, /* 57 */ + 000000, /* 58 */ + 000000, /* 59 */ + 022005, /* == */ + 022005, /* != */ + 024005, /* <= */ + 024005, /* < */ + 024005, /* >= */ + 024005, /* > */ + 024005, /*

p */ + 024005, /* >=p */ + 012213, /* =+ */ + 012213, /* =- */ + 012213, /* =* */ + 012213, /* =/ */ + 012213, /* =% */ + 012253, /* =>> */ + 012253, /* =<< */ + 012253, /* =& */ + 012253, /* =| */ + 012253, /* =^ */ + 012213, /* = */ + 000000, /* 81 */ + 000000, /* 82 */ + 000000, /* 83 */ + 000000, /* 84 */ + 000000, /* 85 */ + 000000, /* 86 */ + 000000, /* 87 */ + 000000, /* 88 */ + 000000, /* 89 */ + 014201, /* ? */ + 034200, /* sizeof */ + 000000, /* 92 */ + 000000, /* 93 */ + 000000, /* 94 */ + 000000, /* 95 */ + 000000, /* 96 */ + 000000, /* 97 */ + 000000, /* 98 */ + 000000, /* 99 */ + 036001, /* call */ + 036001, /* mcall */ + 000000, /* goto */ + 000000, /* jump cond */ + 000000, /* branch cond */ + 000000, /* 105 */ + 000000, /* 106 */ + 000000, /* 107 */ + 000000, /* 108 */ + 000000, /* 109 */ + 000000 /* force r0 */ +}; + +/* + * conversion table: + * FTI: float (or double) to integer + * ITF: integer to float + * ITP: integer to pointer + * ITL: integer to long + * LTI: long to integer + * LTF: long to float + * FTL: float to long + * PTI: pointer to integer + * XX: usually illegal + * When FTI, LTI, FTL are added in they specify + * that it is the left operand that should be converted. + * For + this is done and the conversion is turned back into + * ITF, ITL, LTF. + * For = however the left operand can't be converted + * and the specified conversion is applied to the rhs. + */ +char cvtab[4][4] { +/* int double long ptr */ +/* int */ 0, (FTI<<4)+ITF, (LTI<<4)+ITL, (ITP<<4)+ITP, +/* double */ ITF, 0, LTF, XX, +/* long */ ITL, (FTL<<4)+LTF, 0, XX, +/* ptr */ ITP, XX, XX, PTI +}; + +/* + * character type table + */ +char ctab[] { + EOF, INSERT, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, SPACE, NEWLN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + SPACE, EXCLA, DQUOTE, UNKN, UNKN, MOD, AND, SQUOTE, + LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, PERIOD, DIVIDE, + DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, + DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, EXOR, LETTER, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, COMPL, UNKN +}; diff --git a/usr/source/c/c0h.c b/usr/source/c/c0h.c new file mode 100644 index 0000000000..90b67db398 --- /dev/null +++ b/usr/source/c/c0h.c @@ -0,0 +1,351 @@ +# +/* + + C compiler-- pass 1 header + + +*/ + +/* + parameters +*/ + +#define ncps 8 +#define hshsiz 200 +#define cmsiz 40 +#define swsiz 200 +#define OSSIZ 500 +#define dimsiz 100 +#define NBPW 16 +#define NBPC 8 +#define NCPW 2 +#define STRSIZ 256 + +struct tnode { + int op; + int type; + int dimp; + struct tnode *tr1, *tr2; +}; + +struct { + int op; + int type; + char ssp; /* subscript list */ + char lenp; /* structure length */ +}; + +struct tname { + int op; + int type; + int dimp; + int class; + int offset; + int nloc; +}; + +struct txname { + int op; + int type; + int dimp; + int class; + int offset; + char nname[ncps]; +}; + +struct tconst { + int op; + int type; + int dimp; + int value; +}; + +struct hshtab { + char hclass; + char hflag; + int htype; + int hdimp; + int hoffset; + char name[ncps]; +}; + +struct { + char hclass; + char hflag; + int htype; + char flen; /* Field length */ + char bitoffs; /* Offset of field */ +}; + +struct swtab { + int swlab; + int swval; +}; + +struct bnode { + int bop; + struct tnode *btree; + int lbl; + int cond; +}; + +char cvtab[4][4]; +char savstr[STRSIZ]; +char *strptr; +int opdope[]; +char ctab[]; +char symbuf[ncps+2]; +int hshused; +struct hshtab hshtab[hshsiz]; +int *space; +int *cp; +int cmst[cmsiz]; +int isn; +struct swtab swtab[swsiz]; +struct swtab *swp; +int contlab; +int brklab; +int retlab; +int deflab; +int nauto; +int autolen; +int peeksym; +int peekc; +int eof; +int line; +int osspace[OSSIZ]; +int *treespace; +struct hshtab *defsym; +struct hshtab *funcsym; +int xdflg; +int proflg; +int stflg; +struct hshtab *csym; +int cval; +double fcval; +int nchstr; +int nerror; +struct hshtab *paraml; +struct hshtab *parame; +int strflg; +int mosflg; +int initflg; +int inhdr; +int dimtab[dimsiz]; +char obuf[518]; +char sbuf[518]; +int dimp; +int regvar; +int bitoffs; +struct tname funcblk; + +/* + operators +*/ +#define EOF 0 +#define SEMI 1 +#define LBRACE 2 +#define RBRACE 3 +#define LBRACK 4 +#define RBRACK 5 +#define LPARN 6 +#define RPARN 7 +#define COLON 8 +#define COMMA 9 +#define FSEL 10 + +#define KEYW 19 +#define NAME 20 +#define CON 21 +#define STRING 22 +#define FCON 23 +#define SFCON 24 + +#define SIZEOF 91 +#define INCBEF 30 +#define DECBEF 31 +#define INCAFT 32 +#define DECAFT 33 +#define EXCLA 34 +#define AMPER 35 +#define STAR 36 +#define NEG 37 +#define COMPL 38 + +#define DOT 39 +#define PLUS 40 +#define MINUS 41 +#define TIMES 42 +#define DIVIDE 43 +#define MOD 44 +#define RSHIFT 45 +#define LSHIFT 46 +#define AND 47 +#define OR 48 +#define EXOR 49 +#define ARROW 50 +#define ITOF 51 +#define FTOI 52 +#define LOGAND 53 +#define LOGOR 54 +#define FTOL 56 +#define LTOF 57 +#define ITOL 58 +#define LTOI 59 + +#define EQUAL 60 +#define NEQUAL 61 +#define LESSEQ 62 +#define LESS 63 +#define GREATEQ 64 +#define GREAT 65 +#define LESSEQP 66 +#define LESSP 67 +#define GREATQP 68 +#define GREATP 69 + +#define ASPLUS 70 +#define ASMINUS 71 +#define ASTIMES 72 +#define ASDIV 73 +#define ASMOD 74 +#define ASRSH 75 +#define ASLSH 76 +#define ASSAND 77 +#define ASOR 78 +#define ASXOR 79 +#define ASSIGN 80 + +#define QUEST 90 +#define CALL 100 +#define MCALL 101 +#define JUMP 102 +#define CBRANCH 103 +#define INIT 104 +#define SETREG 105 +#define RFORCE 110 +#define BRANCH 111 +#define LABEL 112 +#define NLABEL 113 +#define RLABEL 114 + +/* + types +*/ +#define INT 0 +#define CHAR 1 +#define FLOAT 2 +#define DOUBLE 3 +#define STRUCT 4 +#define RSTRUCT 5 +#define LONG 6 +#define NOTYPE 7 /* used internally */ + +#define ALIGN 01 +#define TYPE 07 +#define TYLEN 2 +#define XTYPE (03<<3) +#define PTR 010 +#define FUNC 020 +#define ARRAY 030 + +/* + storage classes +*/ +#define KEYWC 1 +#define MOS 10 +#define AUTO 11 +#define EXTERN 12 +#define STATIC 13 +#define REG 14 +#define STRTAG 15 +#define ARG 16 +#define ARG1 17 +#define FMOS 18 + +/* + keywords +*/ +#define GOTO 20 +#define RETURN 21 +#define IF 22 +#define WHILE 23 +#define ELSE 24 +#define SWITCH 25 +#define CASE 26 +#define BREAK 27 +#define CONTIN 28 +#define DO 29 +#define DEFAULT 30 +#define FOR 31 + +/* + characters +*/ +#define INSERT 119 +#define PERIOD 120 +#define SQUOTE 121 +#define DQUOTE 122 +#define LETTER 123 +#define DIGIT 124 +#define NEWLN 125 +#define SPACE 126 +#define UNKN 127 + +/* + * Special operators in intermediate code + */ +#define BDATA 200 +#define WDATA 201 +#define PROG 202 +#define DATA 203 +#define BSS 204 +#define CSPACE 205 +#define SSPACE 206 +#define SYMDEF 207 +#define SAVE 208 +#define RETRN 209 +#define EVEN 210 +#define PROFIL 212 +#define SWIT 213 +#define EXPR 214 +#define SNAME 215 +#define RNAME 216 +#define ANAME 217 +#define NULL 218 + +/* + Flag bits +*/ + +#define BINARY 01 +#define LVALUE 02 +#define RELAT 04 +#define ASSGOP 010 +#define LWORD 020 +#define RWORD 040 +#define COMMUTE 0100 +#define RASSOC 0200 +#define LEAF 0400 + +/* + * Conversion codes + */ +#define ITF 1 +#define ITL 2 +#define LTF 3 +#define ITP 4 +#define PTI 5 +#define FTI 6 +#define LTI 7 +#define FTL 8 +#define XX 15 + +/* + * symbol table flags + */ + +#define FNDEL 01 +#define FNUND 02 +#define FKEYW 04 +#define FFIELD 020 diff --git a/usr/source/c/c10.c b/usr/source/c/c10.c new file mode 100644 index 0000000000..a3fc68b766 --- /dev/null +++ b/usr/source/c/c10.c @@ -0,0 +1,922 @@ +# +/* + + C compiler, part 2 + + +*/ + +#include "c1h.c" + +char maprel[] { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ, + LESS, GREATQP, GREATP, LESSEQP, LESSP +}; + +char notrel[] { NEQUAL, EQUAL, GREAT, GREATEQ, LESS, + LESSEQ, GREATP, GREATQP, LESSP, LESSEQP +}; + +struct tconst czero { CON, INT, 0, 0}; +struct tconst cone { CON, INT, 0, 1}; +struct tconst fczero { SFCON, DOUBLE, 0, 0 }; + +struct table *cregtab; + +int nreg 3; +int isn 10000; +int namsiz 8; + +main(argc, argv) +char *argv[]; +{ + extern fout; + + if (argc<4) { + error("Arg count"); + exit(1); + } + if(fopen(argv[1], ascbuf)<0) { + error("Missing temp file"); + exit(1); + } + if ((fout = creat(argv[3], 0666)) < 0) { + error("Can't create %s", argv[3]); + exit(1); + } + spacep = treespace; + getree(); + /* + * If any floating-point instructions + * were used, generate a reference which + * pulls in the floating-point part of printf. + */ + if (nfloat) + printf(".globl fltused\n"); + /* + * tack on the string file. + */ + close(ascbuf[0]); + if (fopen(argv[2], ascbuf)<0) { + error("Missing temp file"); + exit(1); + } + printf(".globl\n.data\n"); + getree(); + flush(); + exit(nerror!=0); +} + +/* + * Given a tree, a code table, and a + * count of available registers, find the code table + * for the appropriate operator such that the operands + * are of the right type and the number of registers + * required is not too large. + * Return a ptr to the table entry or 0 if none found. + */ +char *match(atree, table, nrleft) +struct tnode *atree; +struct table *table; +{ + int op, d1, d2, t1, t2, dope; + struct tnode *p2; + register struct tnode *p1, *tree; + register struct optab *opt; + + if ((tree=atree)==0) + return(0); + if (table==lsptab) + table = sptab; + if ((op = tree->op)==0) + return(0); + dope = opdope[op]; + if ((dope&LEAF) == 0) + p1 = tree->tr1; + else + p1 = tree; + t1 = p1->type; + d1 = dcalc(p1, nrleft); + if ((dope&BINARY)!=0) { + p2 = tree->tr2; + /* + * If a subtree starts off with a conversion operator, + * try for a match with the conversion eliminated. + * E.g. int = double can be done without generating + * the converted int in a register by + * movf double,fr0; movfi fr0,int . + */ + if(opdope[p1->op]&CNVRT && (opdope[p2->op]&CNVRT)==0) { + tree->tr1 = p1->tr1; + if (opt = match(tree, table, nrleft)) + return(opt); + tree->tr1 = p1; + } else if (opdope[p2->op]&CNVRT && (opdope[p1->op]&CNVRT)==0) { + tree->tr2 = p2->tr1; + if (opt = match(tree, table, nrleft)) + return(opt); + tree->tr2 = p2; + } + t2 = p2->type; + d2 = dcalc(p2, nrleft); + } + for (; table->op!=op; table++) + if (table->op==0) + return(0); + for (opt = table->tabp; opt->tabdeg1!=0; opt++) { + if (d1 > (opt->tabdeg1&077) + || (opt->tabdeg1 >= 0100 && (p1->op != STAR))) + continue; + if (notcompat(p1, opt->tabtyp1, op)) { + continue; + } + if ((opdope[op]&BINARY)!=0 && p2!=0) { + if (d2 > (opt->tabdeg2&077) + || (opt->tabdeg2 >= 0100) && (p2->op != STAR) ) + continue; + if (notcompat(p2,opt->tabtyp2, 0)) + continue; + } + return(opt); + } + return(0); +} + +/* + * Given a tree, a code table, and a register, + * produce code to evaluate the tree with the appropriate table. + * Registers reg and upcan be used. + * If there is a value, it is desired that it appear in reg. + * The routine returns the register in which the value actually appears. + * This routine must work or there is an error. + * If the table called for is cctab, sptab, or efftab, + * and tree can't be done using the called-for table, + * another try is made. + * If the tree can't be compiled using cctab, regtab is + * used and a "tst" instruction is produced. + * If the tree can't be compiled using sptab, + * regtab is used and the register is pushed on the stack. + * If the tree can't be compiled using efftab, + * just use regtab. + * Regtab must succeed or an "op not found" error results. + * + * A number of special cases are recognized, and + * there is an interaction with the optimizer routines. + */ +rcexpr(atree, atable, reg) +struct tnode *atree; +struct table *atable; +{ + register r; + int modf, nargs, recurf; + register struct tnode *tree; + register struct table *table; + + table = atable; + recurf = 0; + if (reg<0) { + recurf++; + reg = ~reg; + if (reg>=020) { + reg =- 020; + recurf++; + } + } + if((tree=atree)==0) + return(0); + switch (tree->op) { + + /* + * A conditional branch + */ + case CBRANCH: + cbranch(optim(tree->btree), tree->lbl, tree->cond, 0); + return(0); + + /* + * An initializing expression + */ + case INIT: + if (tree->tr1->op == AMPER) + tree->tr1 = tree->tr1->tr1; + if (tree->tr1->op==NAME) + pname(tree->tr1); + else if (tree->tr1==CON) + psoct(tree->tr1->value); + else + error("Illegal initialization"); + putchar('\n'); + return(0); + + /* + * Put the value of an expression in r0, + * for a switch or a return + */ + case RFORCE: + if((r=rcexpr(tree->tr1, regtab, reg)) != 0) + printf("mov%c r%d,r0\n", isfloat(tree->tr1), r); + return(0); + + /* + * sequential execution + */ + case COMMA: + rcexpr(tree->tr1, efftab, reg); + atree = tree = tree->tr2; + break; + + /* + * In the generated &~ operator, + * fiddle things so a PDP-11 "bit" + * instruction will be produced when cctab is used. + */ + case NAND: + if (table==cctab) { + tree->op = TAND; + tree->tr2 = optim(block(1, COMPL, INT, 0, tree->tr2)); + } + break; + + + /* + * Handle a subroutine call. It has to be done + * here because if cexpr got called twice, the + * arguments might be compiled twice. + * There is also some fiddling so the + * first argument, in favorable circumstances, + * goes to (sp) instead of -(sp), reducing + * the amount of stack-popping. + */ + case CALL: + r = 0; + nargs = 0; + modf = 0; + if (tree->tr1->op!=NAME) { /* get nargs right */ + nargs++; + nstack++; + } + tree = tree->tr2; + if(tree->op) { + while (tree->op==COMMA) { + r =+ comarg(tree->tr2, &modf); + tree = tree->tr1; + nargs++; + } + r =+ comarg(tree, &modf); + nargs++; + } + tree = atree; + tree->op = CALL2; + if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN) + tree->op = CALL1; + cexpr(tree, regtab, reg); + popstk(r); + nstack =- nargs; + if (table==efftab || table==regtab) + return(0); + r = 0; + goto fixup; + + /* + * Longs need special treatment. + */ + case ASLSH: + case LSHIFT: + if (tree->type==LONG) { + if (tree->tr2->op==ITOL) + tree->tr2 = tree->tr2->tr1; + if (tree->op==ASLSH) + tree->op = ASLSHL; + else + tree->op = LLSHIFT; + } + break; + + /* + * Try to change * and / to shifts. + */ + case TIMES: + case DIVIDE: + case ASTIMES: + case ASDIV: + tree = pow2(tree); + } + /* + * Try to find postfix ++ and -- operators that can be + * pulled out and done after the rest of the expression + */ + if (table!=cctab && table!=cregtab && recurf<2 + && (opdope[tree->op]&LEAF)==0) { + if (r=delay(&atree, table, reg)) { + tree = atree; + table = efftab; + reg = r-1; + } + } + /* + * Basically, try to reorder the computation + * so reg = x+y is done as reg = x; reg =+ y + */ + if (recurf==0 && reorder(&atree, table, reg)) { + if (table==cctab && atree->op==NAME) + return(reg); + } + tree = atree; + if (table==efftab && tree->op==NAME) + return(reg); + if ((r=cexpr(tree, table, reg))>=0) + return(r); + if (table!=regtab) { + if((r=cexpr(tree, regtab, reg))>=0) { + fixup: + modf = isfloat(tree); + if (table==sptab || table==lsptab) { + if (tree->type==LONG) { + printf("mov\tr%d,-(sp)\n",r+1); + nstack++; + } + printf("mov%c r%d,%c(sp)\n", modf, r, + table==sptab? '-':0); + nstack++; + } + if (table==cctab) + printf("tst%c r%d\n", modf, r); + return(r); + } + } + if (tree->op>0 && tree->opop]) + error("No code table for op: %s", opntab[tree->op]); + else + error("No code table for op %d", tree->op); + return(reg); +} + +/* + * Try to compile the tree with the code table using + * registers areg and up. If successful, + * return the register where the value actually ended up. + * If unsuccessful, return -1. + * + * Most of the work is the macro-expansion of the + * code table. + */ +cexpr(atree, table, areg) +struct tnode *atree; +struct table *table; +{ + int c, r; + register struct tnode *p, *p1, *tree; + struct table *ctable; + struct tnode *p2; + char *string; + int reg, reg1, rreg, flag, opd; + char *opt; + + tree = atree; + reg = areg; + p1 = tree->tr2; + c = tree->op; + opd = opdope[c]; + /* + * When the value of a relational or a logical expression is + * desired, more work must be done. + */ + if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) { + cbranch(tree, c=isn++, 1, reg); + rcexpr(&czero, table, reg); + branch(isn, 0); + label(c); + rcexpr(&cone, table, reg); + label(isn++); + return(reg); + } + if(c==QUEST) { + if (table==cctab) + return(-1); + cbranch(tree->tr1, c=isn++, 0, reg); + flag = nstack; + rreg = rcexpr(p1->tr1, table, reg); + nstack = flag; + branch(r=isn++, 0); + label(c); + reg = rcexpr(p1->tr2, table, rreg); + if (rreg!=reg) + printf("mov%c r%d,r%d\n", + isfloat(tree),reg,rreg); + label(r); + return(rreg); + } + reg = oddreg(tree, reg); + reg1 = reg+1; + /* + * long values take 2 registers. + */ + if (tree->type==LONG && tree->op!=ITOL) + reg1++; + /* + * Leaves of the expression tree + */ + if ((r = chkleaf(tree, table, reg)) >= 0) + return(r); + /* + * x + (-1) is better done as x-1. + */ + + if ((tree->op==PLUS||tree->op==ASPLUS) && + (p1=tree->tr2)->op == CON && p1->value == -1) { + p1->value = 1; + tree->op =+ (MINUS-PLUS); + } + if (table==cregtab) + table = regtab; + /* + * The following peculiar code depends on the fact that + * if you just want the codition codes set, efftab + * will generate the right code unless the operator is + * postfix ++ or --. Unravelled, if the table is + * cctab and the operator is not special, try first + * for efftab; if the table isn't, if the operator is, + * or the first match fails, try to match + * with the table actually asked for. + */ + if (table!=cctab || c==INCAFT || c==DECAFT + || (opt = match(tree, efftab, nreg-reg)) == 0) + if ((opt=match(tree, table, nreg-reg))==0) + return(-1); + string = opt->tabstring; + p1 = tree->tr1; + p2 = 0; + if (opdope[tree->op]&BINARY) + p2 = tree->tr2; +loop: + /* + * The 0200 bit asks for a tab. + */ + if ((c = *string++) & 0200) { + c =& 0177; + putchar('\t'); + } + switch (c) { + + case '\0': + if (!isfloat(tree)) + if (tree->op==DIVIDE || tree->op==ASDIV) + reg--; + return(reg); + + /* A1 */ + case 'A': + p = p1; + goto adr; + + /* A2 */ + case 'B': + p = p2; + goto adr; + + adr: + c = 0; + if (*string=='\'') { + c = 1; + string++; + } else if (*string=='+') { + c = 2; + string++; + } + pname(p, c); + goto loop; + + /* I */ + case 'M': + if ((c = *string)=='\'') + string++; + else + c = 0; + prins(tree->op, c, instab); + goto loop; + + /* B1 */ + case 'C': + if ((opd&LEAF) != 0) + p = tree; + else + p = p1; + goto pbyte; + + /* BF */ + case 'P': + p = tree; + goto pb1; + + /* B2 */ + case 'D': + p = p2; + pbyte: + if (p->type==CHAR) + putchar('b'); + pb1: + if (isfloat(p)) + putchar('f'); + goto loop; + + /* BE */ + case 'L': + if (p1->type==CHAR || p2->type==CHAR) + putchar('b'); + p = tree; + goto pb1; + + /* F */ + case 'G': + p = p1; + flag = 01; + goto subtre; + + /* S */ + case 'K': + p = p2; + flag = 02; + goto subtre; + + /* H */ + case 'H': + p = tree; + flag = 04; + + subtre: + ctable = regtab; + c = *string++ - 'A'; + if (*string=='!') { + string++; + c =| 020; /* force right register */ + } + if ((c&02)!=0) + ctable = sptab; + if ((c&04)!=0) + ctable = cctab; + if ((flag&01) && ctable==regtab && (c&01)==0 + && (tree->op==DIVIDE||tree->op==MOD + || tree->op==ASDIV||tree->op==ASMOD)) + ctable = cregtab; + if ((c&01)!=0) { + p = p->tr1; + if(collcon(p) && ctable!=sptab) { + if (p->op==STAR) + p = p->tr1; + p = p->tr1; + } + } + if (table==lsptab && ctable==sptab) + ctable = lsptab; + if (c&010) + r = reg1; + else + if (opdope[p->op]&LEAF || p->degree < 2) + r = reg; + else + r = areg; + rreg = rcexpr(p, ctable, r); + if (ctable!=regtab && ctable!=cregtab) + goto loop; + if (c&010) { + if (c&020 && rreg!=reg1) + printf("mov%c r%d,r%d\n", + isfloat(tree),rreg,reg1); + else + reg1 = rreg; + } else if (rreg!=reg) + if ((c&020)==0 && oddreg(tree, 0)==0 && (flag&04 || + flag&01 + && xdcalc(p2, nreg-rreg-1) <= (opt->tabdeg2&077) + || flag&02 + && xdcalc(p1,nreg-rreg-1) <= (opt->tabdeg1&077))) { + reg = rreg; + reg1 = rreg+1; + } else + printf("mov%c\tr%d,r%d\n", + isfloat(tree), rreg, reg); + goto loop; + + /* R */ + case 'I': + r = reg; + if (*string=='-') { + string++; + r--; + } + goto preg; + + /* R1 */ + case 'J': + r = reg1; + preg: + if (*string=='+') { + string++; + r++; + } + if (r>nreg) + error("Register overflow: simplify expression"); + printf("r%d", r); + goto loop; + + case '-': /* check -(sp) */ + if (*string=='(') { + nstack++; + if (table!=lsptab) + putchar('-'); + goto loop; + } + break; + + case ')': /* check (sp)+ */ + putchar(')'); + if (*string=='+') + nstack--; + goto loop; + + /* #1 */ + case '#': + p = p1->tr1; + goto nmbr; + + /* #2 */ + case '"': + p = p2->tr1; + + nmbr: + if(collcon(p)) { + if (p->op==STAR) { + printf("*"); + p = p->tr1; + } + if ((p = p->tr2)->op == CON) { + if (p->value) + psoct(p->value); + } else if (p->op==AMPER) + pname(p->tr1, 0); + } + goto loop; + + case 'T': /* "tst R" if 1st op not in cctab */ + if (dcalc(p1, 5)>12 && !match(p1, cctab, 10)) + printf("tst r%d\n", reg); + goto loop; + case 'V': /* adc or sbc as required for longs */ + switch(tree->op) { + case PLUS: + case ASPLUS: + case INCBEF: + case INCAFT: + printf("adc"); + break; + + case MINUS: + case ASMINUS: + case NEG: + case DECBEF: + case DECAFT: + printf("sbc"); + break; + + default: + while ((c = *string++)!='\n' && c!='\0'); + break; + } + goto loop; + } + putchar(c); + goto loop; +} + +/* + * This routine just calls sreorder (below) + * on the subtrees and then on the tree itself. + * It returns non-zero if anything changed. + */ +reorder(treep, table, reg) +struct tnode **treep; +struct table *table; +{ + register r, r1; + register struct tnode *p; + + p = *treep; + if (opdope[p->op]&LEAF) + return(0); + r1 = 0; + while(sreorder(&p->tr1, table, reg)) + r1++; + if (opdope[p->op]&BINARY) + while(sreorder(&p->tr2, table, reg)) + r1++; + r = 0; + while (sreorder(treep, table, reg)) + r++; + *treep = optim(*treep); + return(r); +} + +/* + * Basically this routine carries out two kinds of optimization. + * First, it observes that "x + (reg = y)" where actually + * the = is any assignment op is better done as "reg=y; x+reg". + * In this case rcexpr is called to do the first part and the + * tree is modified so the name of the register + * replaces the assignment. + * Moreover, expressions like "reg = x+y" are best done as + * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!). + */ +sreorder(treep, table, reg) +struct tnode **treep; +struct table *table; +{ + register struct tnode *p, *p1; + + p = *treep; + if (opdope[p->op]&LEAF) + return(0); + if (p->op==PLUS) + if (reorder(&p->tr2, table, reg)) + *treep = p = optim(p); + p1 = p->tr1; + if (p->op==STAR || p->op==PLUS) { + if (reorder(&p->tr1, table, reg)) + *treep = p = optim(p); + p1 = p->tr1; + } + if (p1->op==NAME) switch(p->op) { + case ASLSH: + case ASRSH: + case ASSIGN: + if (p1->class != REG || isfloat(p->tr2)) + return(0); + if (p->op==ASSIGN) switch (p->tr2->op) { + case TIMES: + case DIVIDE: + if (!ispow2(p->tr2)) + break; + p->tr2 = pow2(p->tr2); + case PLUS: + case MINUS: + case AND: + case NAND: + case OR: + case EXOR: + case LSHIFT: + case RSHIFT: + p1 = p->tr2->tr2; + if (xdcalc(p1) > 12 + || p1->op==NAME + &&(p1->nloc==p->tr1->nloc + || p1->regno==p->tr1->nloc)) + return(0); + p1 = p->tr2; + p->tr2 = p1->tr1; + if (p1->tr1->op!=NAME + || p1->tr1->class!=REG + || p1->tr1->nloc!=p->tr1->nloc) + rcexpr(p, efftab, reg); + p->tr2 = p1->tr2; + p->op = p1->op + ASPLUS - PLUS; + *treep = p; + return(1); + } + goto OK; + + case ASTIMES: + case ASDIV: + if (!ispow2(p)) + return(0); + case ASPLUS: + case ASMINUS: + case ASSAND: + case ASSNAND: + case ASOR: + case ASXOR: + case DECBEF: + case INCBEF: + OK: + if (table==cctab||table==cregtab) + reg =+ 020; + rcexpr(optim(p), efftab, ~reg); + *treep = p1; + return(1); + } + return(0); +} + +/* + * Delay handles postfix ++ and -- + * It observes that "x + y++" is better + * treated as "x + y; y++". + * If the operator is ++ or -- itself, + * it calls rcexpr to load the operand, letting + * the calling instance of rcexpr to do the + * ++ using efftab. + * Otherwise it uses sdelay to search for inc/dec + * among the operands. + */ +delay(treep, table, reg) +struct tnode **treep; +{ + register struct tnode *p, *p1; + register r; + + p = *treep; + if (table!=efftab && (p->op==INCAFT||p->op==DECAFT) + && p->tr1->op==NAME) { + return(1+rcexpr(p->tr1, table, reg)); + } + p1 = 0; + if (opdope[p->op]&BINARY) + p1 = sdelay(&p->tr2); + if (p1==0) + p1 = sdelay(&p->tr1); + if (p1) { + r = rcexpr(optim(p), table, reg); + *treep = p1; + return(r+1); + } + return(0); +} + +sdelay(ap) +struct tnode **ap; +{ + register struct tnode *p, *p1; + + p = *ap; + if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) { + *ap = ncopy(p->tr1); + return(p); + } + if (p->op==STAR || p->op==PLUS) + if (p1=sdelay(&p->tr1)) + return(p1); + if (p->op==PLUS) + return(sdelay(&p->tr2)); + return(0); +} + +/* + * Copy a tree node for a register variable. + * Used by sdelay because if *reg-- is turned + * into *reg; reg-- the *reg will in turn + * be changed to some offset class, accidentally + * modifying the reg--. + */ +ncopy(ap) +struct tname *ap; +{ + register struct tname *p; + + p = ap; + if (p->class!=REG) + return(p); + return(block(3, NAME, p->type, p->elsize, p->tr1, + p->offset, p->nloc)); +} + +/* + * If the tree can be immediately loaded into a register, + * produce code to do so and return success. + */ +chkleaf(atree, table, reg) +struct tnode *atree; +{ + struct tnode lbuf; + register struct tnode *tree; + + tree = atree; + if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12) + return(-1); + lbuf.op = LOAD; + lbuf.type = tree->type; + lbuf.degree = tree->degree; + lbuf.tr1 = tree; + return(rcexpr(&lbuf, table, reg)); +} + +/* + * Compile a function argument. + * If the stack is currently empty, put it in (sp) + * rather than -(sp); this will save a pop. + * Return the number of bytes pushed, + * for future popping. + */ +comarg(atree, flagp) +int *flagp; +{ + register struct tnode *tree; + register retval; + + tree = atree; + if (nstack || isfloat(tree) || tree->type==LONG) { + rcexpr(tree, sptab, 0); + retval = arlength(tree->type); + } else { + (*flagp)++; + rcexpr(tree, lsptab, 0); + retval = 0; + } + return(retval); +} diff --git a/usr/source/c/c11.c b/usr/source/c/c11.c new file mode 100644 index 0000000000..8c88291022 --- /dev/null +++ b/usr/source/c/c11.c @@ -0,0 +1,849 @@ +# +/* + * C compiler + */ + +#include "c1h.c" + +max(a, b) +{ + if (a>b) + return(a); + return(b); +} + +degree(at) +struct tnode *at; +{ + register struct tnode *t, *t1; + + if ((t=at)==0 || t->op==0) + return(0); + if (t->op == CON) + return(-3); + if (t->op == AMPER) + return(-2); + if (t->op==ITOL && (t1 = isconstant(t)) && t1->value>= 0) + return(-2); + if ((opdope[t->op] & LEAF) != 0) { + if (t->type==CHAR || t->type==FLOAT) + return(1); + return(0); + } + return(t->degree); +} + +pname(ap, flag) +struct tnode *ap; +{ + register i; + register struct tnode *p; + + p = ap; +loop: + switch(p->op) { + + case SFCON: + case CON: + printf("$"); + psoct(p->value); + return; + + case FCON: + printf("L%d", p->value); + return; + + case NAME: + i = p->offset; + if (flag==2) + i =+ 2; + if (i) { + psoct(i); + if (p->class!=OFFS) + putchar('+'); + if (p->class==REG) + regerr(); + } + switch(p->class) { + + case SOFFS: + case XOFFS: + pbase(p); + + case OFFS: + printf("(r%d)", p->regno); + return; + + case EXTERN: + case STATIC: + pbase(p); + return; + + case REG: + printf("r%d", p->nloc); + return; + + } + error("Compiler error: pname"); + return; + + case AMPER: + putchar('$'); + p = p->tr1; + if (p->op==NAME && p->class==REG) + regerr(); + goto loop; + + case AUTOI: + printf("(r%d)%c", p->nloc, flag==1?0:'+'); + return; + + case AUTOD: + printf("%c(r%d)", flag==1?0:'-', p->nloc); + return; + + case STAR: + p = p->tr1; + putchar('*'); + goto loop; + + } + error("pname called illegally"); +} + +regerr() +{ + error("Illegal use of register"); +} + +pbase(ap) +struct tnode *ap; +{ + register struct tnode *p; + + p = ap; + if (p->class==SOFFS || p->class==STATIC) + printf("L%d", p->nloc); + else + printf("_%.8s", &(p->nloc)); +} + +xdcalc(ap, nrleft) +struct tnode *ap; +{ + register struct tnode *p; + register d; + + p = ap; + d = dcalc(p, nrleft); + if (d<20 && p->type==CHAR) { + if (nrleft>=1) + d = 20; + else + d = 24; + } + return(d); +} + +dcalc(ap, nrleft) +struct tnode *ap; +{ + register struct tnode *p, *p1; + + if ((p=ap)==0) + return(0); + switch (p->op) { + + case NAME: + if (p->class==REG) + return(9); + + case AMPER: + case FCON: + case AUTOI: + case AUTOD: + return(12); + + case CON: + case SFCON: + if (p->value==0) + return(4); + if (p->value==1) + return(5); + if (p->value > 0) + return(8); + return(12); + + case STAR: + p1 = p->tr1; + if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD) + if (p->type!=LONG) + return(12); + } + if (p->type==LONG) + nrleft--; + return(p->degree <= nrleft? 20: 24); +} + +notcompat(ap, ast, op) +struct tnode *ap; +{ + register at, st; + register struct tnode *p; + + p = ap; + at = p->type; + st = ast; + if (st==0) /* word, byte */ + return(at>CHAR && atINT && atop==NAME && p->class==REG && op==ASSIGN && st==CHAR) + return(0); + return(st != at); +} + +prins(op, c, itable) +struct instab *itable; +{ + register struct instab *insp; + register char *ip; + + for (insp=itable; insp->op != 0; insp++) { + if (insp->op == op) { + ip = c? insp->str2: insp->str1; + if (ip==0) + break; + printf("%s", ip); + return; + } + } + error("No match' for op %d", op); +} + +collcon(ap) +struct tnode *ap; +{ + register op; + register struct tnode *p; + + p = ap; + if (p->op==STAR) + p = p->tr1; + if (p->op==PLUS) { + op = p->tr2->op; + if (op==CON || op==AMPER) + return(1); + } + return(0); +} + +isfloat(at) +struct tnode *at; +{ + register struct tnode *t; + + t = at; + if ((opdope[t->op]&RELAT)!=0) + t = t->tr1; + if (t->type==FLOAT || t->type==DOUBLE) { + nfloat = 1; + return('f'); + } + return(0); +} + +oddreg(t, areg) +struct tnode *t; +{ + register reg; + + reg = areg; + if (!isfloat(t)) + switch(t->op) { + case DIVIDE: + case MOD: + case ASDIV: + case ASMOD: + reg++; + + case TIMES: + case ASTIMES: + return(reg|1); + } + return(reg); +} + +arlength(t) +{ + if (t>=PTR) + return(2); + switch(t) { + + case INT: + case CHAR: + return(2); + + case LONG: + return(4); + + case FLOAT: + case DOUBLE: + return(8); + } + return(1024); +} + +/* + * Strings for switch code. + */ + +char dirsw[] {"\ +cmp r0,$%o\n\ +jhi L%d\n\ +asl r0\n\ +jmp *L%d(r0)\n\ +.data\n\ +L%d:\ +" }; + +char simpsw[] {"\ +mov $L%d,r1\n\ +mov r0,L%d\n\ +L%d:cmp r0,(r1)+\n\ +jne L%d\n\ +jmp *L%d-L%d(r1)\n\ +.data\n\ +L%d:\ +"}; + +char hashsw[] {"\ +mov r0,r1\n\ +clr r0\n\ +div $%o,r0\n\ +asl r1\n\ +add $L%d,r1\n\ +mov r0,*(r1)+\n\ +mov (r1)+,r1\n\ +L%d:cmp r0,-(r1)\n\ +jne L%d\n\ +jmp *L%d-L%d(r1)\n\ +.data\n\ +L%d:\ +"}; + +pswitch(afp, alp, deflab) +struct swtab *afp, *alp; +{ + int tlab, ncase, i, j, tabs, worst, best, range; + register struct swtab *swp, *fp, *lp; + int poctab[swsiz]; + + fp = afp; + lp = alp; + if (fp==lp) { + printf("jbr L%d\n", deflab); + return; + } + tlab = isn++; + if (sort(fp, lp)) + return; + ncase = lp-fp; + lp--; + range = lp->swval - fp->swval; + /* direct switch */ + if (range>0 && range <= 3*ncase) { + if (fp->swval) + printf("sub $%o,r0\n", fp->swval); + printf(dirsw, range, deflab, isn, isn); + isn++; + for (i=fp->swval; i<=lp->swval; i++) { + if (i==fp->swval) { + printf("L%d\n", fp->swlab); + fp++; + } else + printf("L%d\n", deflab); + } + goto esw; + } + /* simple switch */ + if (ncase<8) { + i = isn++; + j = isn++; + printf(simpsw, i, j, isn, isn, j, i, i); + isn++; + for (; fp<=lp; fp++) + printf("%o\n", fp->swval); + printf("L%d:..\n", j); + for (fp = afp; fp<=lp; fp++) + printf("L%d\n", fp->swlab); + printf("L%d\n", deflab); + goto esw; + } + /* hash switch */ + best = 077777; + for (i=ncase/4; i<=ncase/2; i++) { + for (j=0; jswval, i)]++; + worst = 0; + for (j=0; jworst) + worst = poctab[j]; + if (i*worst < best) { + tabs = i; + best = i*worst; + } + } + i = isn++; + printf(hashsw, tabs, isn, i, i, isn+tabs+1, isn+1, isn); + isn++; + for (i=0; i<=tabs; i++) + printf("L%d\n", isn+i); + for (i=0; iswval, tabs) == i) + printf("%o\n", ldiv(0, swp->swval, tabs)); + } + printf("L%d:", isn++); + for (i=0; iswval, tabs) == i) + printf("L%d\n", swp->swlab); + } +esw: + printf(".text\n"); +} + +sort(afp, alp) +struct swtab *afp, *alp; +{ + register struct swtab *cp, *fp, *lp; + int intch, t; + + fp = afp; + lp = alp; + while (fp < --lp) { + intch = 0; + for (cp=fp; cpswval == cp[1].swval) { + error("Duplicate case (%d)", cp->swval); + return(1); + } + if (cp->swval > cp[1].swval) { + intch++; + t = cp->swval; + cp->swval = cp[1].swval; + cp[1].swval = t; + t = cp->swlab; + cp->swlab = cp[1].swlab; + cp[1].swlab = t; + } + } + if (intch==0) + break; + } + return(0); +} + +ispow2(atree) +{ + register int d; + register struct tnode *tree; + + tree = atree; + if (!isfloat(tree) && tree->tr2->op==CON) { + d = tree->tr2->value; + if (d>1 && (d&(d-1))==0) + return(d); + } + return(0); +} + +pow2(atree) +struct tnode *atree; +{ + register int d, i; + register struct tnode *tree; + + tree = atree; + if (d = ispow2(tree)) { + for (i=0; (d=>>1)!=0; i++); + tree->tr2->value = i; + d = tree->op; + tree->op = d==TIMES? LSHIFT: + (d==DIVIDE? RSHIFT: + (d==ASTIMES? ASLSH: ASRSH)); + tree = optim(tree); + } + return(tree); +} + +cbranch(atree, albl, cond, areg) +struct tnode *atree; +{ + int l1, op; + register lbl, reg; + register struct tnode *tree; + + lbl = albl; + reg = areg; + if ((tree=atree)==0) + return; + switch(tree->op) { + + case LOGAND: + if (cond) { + cbranch(tree->tr1, l1=isn++, 0, reg); + cbranch(tree->tr2, lbl, 1, reg); + label(l1); + } else { + cbranch(tree->tr1, lbl, 0, reg); + cbranch(tree->tr2, lbl, 0, reg); + } + return; + + case LOGOR: + if (cond) { + cbranch(tree->tr1, lbl, 1, reg); + cbranch(tree->tr2, lbl, 1, reg); + } else { + cbranch(tree->tr1, l1=isn++, 1, reg); + cbranch(tree->tr2, lbl, 0, reg); + label(l1); + } + return; + + case EXCLA: + cbranch(tree->tr1, lbl, !cond, reg); + return; + + case COMMA: + rcexpr(tree->tr1, efftab, reg); + tree = tree->tr2; + break; + } + op = tree->op; + if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) { + if (tree->type!=LONG) { + tree->op = MINUS; + tree->type = LONG; + tree = optim(tree); + } else + op = NEQUAL; + rcexpr(tree, regtab, 0); + printf("ashc $0,r0\n"); + branch(lbl, op, !cond); + return; + } + rcexpr(tree, cctab, reg); + op = tree->op; + if ((opdope[op]&RELAT)==0) + op = NEQUAL; + else { + l1 = tree->tr2->op; + if ((l1==CON || l1==SFCON) && tree->tr2->value==0) + op =+ 200; /* special for ptr tests */ + else + op = maprel[op-EQUAL]; + } + if (isfloat(tree)) + printf("cfcc\n"); + branch(lbl, op, !cond); +} + +branch(lbl, aop, c) +{ + register op; + + if(op=aop) + prins(op, c, branchtab); + else + printf("jbr"); + printf("\tL%d\n", lbl); +} + +label(l) +{ + printf("L%d:", l); +} + +popstk(a) +{ + switch(a) { + + case 0: + return; + + case 2: + printf("tst (sp)+\n"); + return; + + case 4: + printf("cmp (sp)+,(sp)+\n"); + return; + } + printf("add $%o,sp\n", a); +} + +error(s, p1, p2, p3, p4, p5, p6) +{ + register f; + extern fout; + + nerror++; + flush(); + f = fout; + fout = 1; + printf("%d: ", line); + printf(s, p1, p2, p3, p4, p5, p6); + putchar('\n'); + flush(); + fout = f; +} + +psoct(an) +{ + register int n, sign; + + sign = 0; + if ((n = an) < 0) { + n = -n; + sign = '-'; + } + printf("%c%o", sign, n); +} + +/* + * Read in an intermediate file. + */ +getree() +{ + struct tnode *expstack[20]; + register struct tnode **sp; + register t, op; + static char s[9]; + struct swtab *swp; + + spacep = treespace; + sp = expstack; + for (;;) { + if (sp >= &expstack[20]) + error("Stack botch"); + op = getw(ascbuf); + if ((op&0177400) != 0177000) { + error("Intermediate file error"); + exit(1); + } + switch(op =& 0377) { + + case EOF: + return; + + case BDATA: + printf(".byte "); + seq(','); + break; + + case WDATA: + seq(';'); + break; + + case PROG: + printf(".text\n"); + break; + + case DATA: + printf(".data\n"); + break; + + case BSS: + printf(".bss\n"); + break; + + case SYMDEF: + printf(".globl _%s\n", outname(s)); + break; + + case RETRN: + printf("jmp cret\n"); + break; + + case CSPACE: + t = outname(s); + printf(".comm _%s,%o\n", t, getw(ascbuf)); + break; + + case SSPACE: + printf(".=.+%o\n", getw(ascbuf)); + break; + + case EVEN: + printf(".even\n"); + break; + + case SAVE: + printf("jsr r5,csv\n"); + t = getw(ascbuf)-6; + if (t==2) + printf("tst -(sp)\n"); + else if (t > 2) + printf("sub $%o,sp\n", t); + break; + + case PROFIL: + t = getw(ascbuf); + printf("mov $L%d,r0\njsr pc,mcount\n", t); + printf(".bss\nL%d:.=.+2\n.text\n", t); + break; + + case SNAME: + t = outname(s); + printf("~%s=L%d\n", t, getw(ascbuf)); + break; + + case ANAME: + t = outname(s); + printf("~%s=%o\n", t, getw(ascbuf)); + break; + + case RNAME: + t = outname(s); + printf("~%s=r%d\n", t, getw(ascbuf)); + break; + + case SWIT: + t = getw(ascbuf); + line = getw(ascbuf); + swp = treespace; + while (swp->swlab = getw(ascbuf)) { + swp->swval = getw(ascbuf); + swp++; + } + pswitch(treespace, swp, t); + break; + + case EXPR: + line = getw(ascbuf); + if (sp != &expstack[1]) { + error("Expression input botch\n"); + exit(1); + } + nstack = 0; + rcexpr(optim(*--sp), efftab, 0); + spacep = treespace; + break; + + case NAME: + t = getw(ascbuf); + if (t==EXTERN) { + t = getw(ascbuf); + *sp = block(6, NAME, t, 0, EXTERN, 0, 0,0,0,0); + outname(&(*sp)->nloc); + sp++; + break; + } + *sp = block(3, NAME, 0, 0, t, 0, 0); + (*sp)->type = getw(ascbuf); + (*sp)->nloc = getw(ascbuf); + sp++; + break; + + case CON: + case SFCON: + case FCON: + t = getw(ascbuf); + *sp++ = block(1, op, t, 0, getw(ascbuf)); + break; + + case FSEL: + t = getw(ascbuf); + sp[-1] = block(2, op, t, 0, sp[-1], getw(ascbuf)); + break; + + case NULL: + *sp++ = block(0, 0, 0, 0); + break; + + case CBRANCH: + t = getw(ascbuf); + sp[-1] = block(1, CBRANCH, sp[-1], t, getw(ascbuf)); + break; + + case LABEL: + label(getw(ascbuf)); + break; + + case NLABEL: + printf("_%s:\n", outname(s)); + break; + + case RLABEL: + t = outname(s); + printf("_%s:\n~~%s:\n", t, t); + break; + + case BRANCH: + branch(getw(ascbuf), 0); + break; + + case SETREG: + nreg = getw(ascbuf)-1; + break; + + default: + if (opdope[op]&BINARY) { + if (sp < &expstack[1]) { + error("Binary expression botch"); + exit(1); + } + t = *--sp; + *sp++ = block(2, op, getw(ascbuf), 0, *--sp, t); + } else { + sp[-1] = block(1, op, getw(ascbuf), 0, sp[-1]); + } + break; + } + } +} + +outname(s) +{ + register char *p, c; + register n; + + p = s; + n = 0; + while (c = getc(ascbuf)) { + *p++ = c; + n++; + } + while (n++ < 8) + *p++ = 0; + return(s); +} + +seq(c) +{ + register o; + + if (getw(ascbuf) == 0) + return; + for (;;) { + printf("%o", getw(ascbuf)); + if ((o = getw(ascbuf)) != 1) + break; + printf("%c", c); + } + printf("\n"); +} diff --git a/usr/source/c/c12.c b/usr/source/c/c12.c new file mode 100644 index 0000000000..69961f2c0f --- /dev/null +++ b/usr/source/c/c12.c @@ -0,0 +1,621 @@ +# +/* + * C compiler part 2 -- expression optimizer + * + */ + +#include "c1h.c" + +optim(atree) +struct tnode *atree; +{ + register op, dope; + int d1, d2; + struct tnode *t; + register struct tnode *tree; + + if ((tree=atree)==0) + return(0); + if ((op = tree->op)==0) + return(tree); + if (op==NAME && tree->class==AUTO) { + tree->class = OFFS; + tree->regno = 5; + tree->offset = tree->nloc; + } + dope = opdope[op]; + if ((dope&LEAF) != 0) + return(tree); + if ((dope&BINARY) == 0) + return(unoptim(tree)); + /* is known to be binary */ + if (tree->type==CHAR) + tree->type = INT; + if ((dope&COMMUTE)!=0) { + acomm: d1 = tree->type; + tree = acommute(tree); + tree->type = d1; + /* + * PDP-11 special: + * replace a&b by a NAND ~ b. + * This will be undone when in + * truth-value context. + */ + if (tree->op!=AND) + return(tree); + tree->op = NAND; + tree->tr2 = block(1, COMPL, tree->tr2->type, 0, tree->tr2); + } + again: + tree->tr1 = optim(tree->tr1); + tree->tr2 = optim(tree->tr2); + if ((dope&RELAT) != 0) { + if ((d1=degree(tree->tr1)) < (d2=degree(tree->tr2)) + || d1==d2 && tree->tr1->op==NAME && tree->tr2->op!=NAME) { + t = tree->tr1; + tree->tr1 = tree->tr2; + tree->tr2 = t; + tree->op = maprel[op-EQUAL]; + } + if (tree->tr1->type==CHAR && tree->tr2->op==CON + && (dcalc(tree->tr1) <= 12 || tree->tr1->op==STAR) + && tree->tr2->value <= 127 && tree->tr2->value >= 0) + tree->tr2->type = CHAR; + } + d1 = max(degree(tree->tr1), islong(tree->type)); + d2 = max(degree(tree->tr2), 0); + if (tree->tr1->type==LONG && dope&RELAT) + d1 = 10; + switch (op) { + + case LTIMES: + case LDIV: + case LMOD: + case LASTIMES: + case LASDIV: + case LASMOD: + tree->degree = 10; + break; + + /* + * PDP-11 special: + * generate new =&~ operator out of =& + * by complementing the RHS. + */ + case ASSAND: + op = ASSNAND; + tree->op = op; + tree->tr2 = block(2, COMPL, tree->tr2->type, 0, tree->tr2); + goto again; + + case NAND: + if (isconstant(tree->tr2) && tree->tr2->value==0) + return(tree->tr1); + goto def; + + case CALL: + tree->degree = 10; + break; + + case QUEST: + case COLON: + tree->degree = max(d1, d2); + break; + + case MINUS: + if (t = isconstant(tree->tr2)) { + tree->op = PLUS; + if (t->type==DOUBLE) + /* PDP-11 FP representation */ + t->value =^ 0100000; + else + t->value = -t->value; + goto acomm; + } + goto def; + + case DIVIDE: + case ASDIV: + case ASTIMES: + if (tree->tr2->op==CON && tree->tr2->value==1) + return(tree->tr1); + if (ispow2(tree) == 0) { + + case MOD: + case ASMOD: + d1 =+ 2; + d2 =+ 2; + } + if (tree->type==LONG) + return(hardlongs(tree)); + goto constant; + + case LSHIFT: + case RSHIFT: + case ASRSH: + case ASLSH: + if (tree->tr2->op==CON && tree->tr2->value==0) + return(tree->tr1); + /* + * PDP-11 special: turn right shifts into negative + * left shifts + */ + if (op==LSHIFT||op==ASLSH) + goto constant; + if (tree->tr2->op==CON && tree->tr2->value==1) + goto constant; + op =+ (LSHIFT-RSHIFT); + tree->op = op; + tree->tr2 = block(1, NEG, tree->type, 0, tree->tr2); + goto again; + + constant: + if (tree->tr1->op==CON && tree->tr2->op==CON) { + const(op, &tree->tr1->value, tree->tr2->value); + return(tree->tr1); + } + + + def: + default: + tree->degree = d1==d2? d1+islong(tree->type): max(d1, d2); + break; + } + return(tree); +} + +unoptim(atree) +struct tnode *atree; +{ + register struct tnode *subtre, *tree; + register int *p; + double static fv; + struct { int integer; }; + + if ((tree=atree)==0) + return(0); + if (tree->op==CBRANCH) { + tree->btree = optim(tree->btree); + return(tree); + } + subtre = tree->tr1 = optim(tree->tr1); + switch (tree->op) { + + case FSEL: + tree->tr1 = block(2, RSHIFT, INT, 0, subtre, + block(1, CON, INT, 0, tree->bitoffs)); + tree->op = AND; + tree->type = INT; + tree->tr2 = block(1, CON, INT, 0, (1<flen)-1); + return(optim(tree)); + + case AMPER: + if (subtre->op==STAR) + return(subtre->tr1); + if (subtre->op==NAME && subtre->class == OFFS) { + p = block(2, PLUS, tree->type, 1, subtre, tree); + subtre->type = tree->type; + tree->op = CON; + tree->type = INT; + tree->degree = 0; + tree->value = subtre->offset; + subtre->class = REG; + subtre->nloc = subtre->regno; + subtre->offset = 0; + return(p); + } + break; + + case STAR: + if (subtre->op==AMPER) + return(subtre->tr1); + if (subtre->op==NAME && subtre->class==REG) { + subtre->type = tree->type; + subtre->class = OFFS; + subtre->regno = subtre->nloc; + return(subtre); + } + p = subtre->tr1; + if ((subtre->op==INCAFT||subtre->op==DECBEF)&&tree->type!=LONG + && p->op==NAME && p->class==REG && p->type==subtre->type) { + p->type = tree->type; + p->op = subtre->op==INCAFT? AUTOI: AUTOD; + return(p); + } + if (subtre->op==PLUS && p->op==NAME && p->class==REG) { + if (subtre->tr2->op==CON) { + p->offset =+ subtre->tr2->value; + p->class = OFFS; + p->type = tree->type; + p->regno = p->nloc; + return(p); + } + if (subtre->tr2->op==AMPER) { + subtre = subtre->tr2->tr1; + subtre->class =+ XOFFS-EXTERN; + subtre->regno = p->nloc; + subtre->type = tree->type; + return(subtre); + } + } + break; + case EXCLA: + if ((opdope[subtre->op]&RELAT)==0) + break; + tree = subtre; + tree->op = notrel[tree->op-EQUAL]; + break; + + case NEG: + case COMPL: + if (tree->type==CHAR) + tree->type = INT; + if (tree->op == subtre->op) + return(subtre->tr1); + if (subtre->op==ITOL) { + subtre->op = tree->op; + subtre->type = INT; + tree->op = ITOL; + } + } + if (subtre->op == CON) switch(tree->op) { + + case NEG: + subtre->value = -subtre->value; + return(subtre); + + case COMPL: + subtre->value = ~subtre->value; + return(subtre); + + case ITOF: + fv = subtre->value; + p = &fv; + p++; + if (*p++==0 && *p++==0 && *p++==0) { + subtre->type = DOUBLE; + subtre->value = fv.integer; + subtre->op = SFCON; + return(subtre); + } + break; + } + tree->degree = max(islong(tree->type), degree(subtre)); + return(tree); +} + +struct acl { + int nextl; + int nextn; + struct tnode *nlist[20]; + struct tnode *llist[21]; +}; + +acommute(atree) +{ + struct acl acl; + int d, i, op, flt; + register struct tnode *t1, **t2, *tree; + struct tnode *t; + + acl.nextl = 0; + acl.nextn = 0; + tree = atree; + op = tree->op; + flt = isfloat(tree); + insert(op, tree, &acl); + acl.nextl--; + t2 = &acl.llist[acl.nextl]; + if (!flt) { + /* put constants together */ + for (i=acl.nextl;i>0&&t2[0]->op==CON&&t2[-1]->op==CON;i--) { + acl.nextl--; + t2--; + const(op, &t2[0]->value, t2[1]->value); + } + } + if (op==PLUS || op==OR) { + /* toss out "+0" */ + if (acl.nextl>0 && (t1 = isconstant(*t2)) && t1->value==0) { + acl.nextl--; + t2--; + } + if (acl.nextl <= 0) + return(*t2); + /* subsume constant in "&x+c" */ + if (op==PLUS && t2[0]->op==CON && t2[-1]->op==AMPER) { + t2--; + t2[0]->tr1->offset =+ t2[1]->value; + acl.nextl--; + } + } else if (op==TIMES || op==AND) { + t1 = acl.llist[acl.nextl]; + if (t1->op==CON) { + if (t1->value==0) + return(t1); + if (op==TIMES && t1->value==1 && acl.nextl>0) + if (--acl.nextl <= 0) + return(acl.llist[0]); + } + } + if (op==PLUS && !flt) + distrib(&acl); + tree = *(t2 = &acl.llist[0]); + d = max(degree(tree), islong(tree->type)); + if (op==TIMES && !flt) + d++; + for (i=0; itr2 = t = *++t2; + t1->degree = d = d==degree(t)? d+islong(t1->type): max(d, degree(t)); + t1->tr1 = tree; + tree = t1; + if (tree->type==LONG) { + if (tree->op==TIMES) + tree = hardlongs(tree); + else if (tree->op==PLUS && (t = isconstant(tree->tr1)) + && t->value < 0) { + tree->op = MINUS; + t->value = - t->value; + t = tree->tr1; + tree->tr1 = tree->tr2; + tree->tr2 = t; + } + } + } + if (tree->op==TIMES && ispow2(tree)) + tree->degree = max(degree(tree->tr1), islong(tree->type)); + return(tree); +} + +distrib(list) +struct acl *list; +{ +/* + * Find a list member of the form c1c2*x such + * that c1c2 divides no other such constant, is divided by + * at least one other (say in the form c1*y), and which has + * fewest divisors. Reduce this pair to c1*(y+c2*x) + * and iterate until no reductions occur. + */ + register struct tnode **p1, **p2; + struct tnode *t; + int ndmaj, ndmin; + struct tnode **dividend, **divisor; + struct tnode **maxnod, **mindiv; + + loop: + maxnod = &list->llist[list->nextl]; + ndmaj = 1000; + dividend = 0; + for (p1 = list->llist; p1 <= maxnod; p1++) { + if ((*p1)->op!=TIMES || (*p1)->tr2->op!=CON) + continue; + ndmin = 0; + for (p2 = list->llist; p2 <= maxnod; p2++) { + if (p1==p2 || (*p2)->op!=TIMES || (*p2)->tr2->op!=CON) + continue; + if ((*p1)->tr2->value == (*p2)->tr2->value) { + (*p2)->tr2 = (*p1)->tr1; + (*p2)->op = PLUS; + (*p1)->tr1 = (*p2); + *p1 = optim(*p1); + squash(p2, maxnod); + list->nextl--; + goto loop; + } + if (((*p2)->tr2->value % (*p1)->tr2->value) == 0) + goto contmaj; + if (((*p1)->tr2->value % (*p2)->tr2->value) == 0) { + ndmin++; + mindiv = p2; + } + } + if (ndmin > 0 && ndmin < ndmaj) { + ndmaj = ndmin; + dividend = p1; + divisor = mindiv; + } + contmaj:; + } + if (dividend==0) + return; + t = list->nlist[--list->nextn]; + p1 = dividend; + p2 = divisor; + t->op = PLUS; + t->type = (*p1)->type; + t->tr1 = (*p1); + t->tr2 = (*p2)->tr1; + (*p1)->tr2->value =/ (*p2)->tr2->value; + (*p2)->tr1 = t; + t = optim(*p2); + if (p1 < p2) { + *p1 = t; + squash(p2, maxnod); + } else { + *p2 = t; + squash(p1, maxnod); + } + list->nextl--; + goto loop; +} + +squash(p, maxp) +struct tnode **p, **maxp; +{ + register struct tnode **np; + + for (np = p; np < maxp; np++) + *np = *(np+1); +} + +const(op, vp, av) +int *vp; +{ + register int v; + + v = av; + switch (op) { + + case PLUS: + *vp =+ v; + return; + + case TIMES: + *vp =* v; + return; + + case AND: + *vp =& v; + return; + + case OR: + *vp =| v; + return; + + case EXOR: + *vp =^ v; + return; + + case DIVIDE: + case MOD: + if (v==0) + error("Divide check"); + else + if (op==DIVIDE) + *vp =/ v; + else + *vp =% v; + return; + + case RSHIFT: + *vp =>> v; + return; + + case LSHIFT: + *vp =<< v; + return; + + case NAND: + *vp =& ~ v; + return; + } + error("C error: const"); +} + +insert(op, atree, alist) +struct acl *alist; +{ + register d; + register struct acl *list; + register struct tnode *tree; + int d1, i; + struct tnode *t; + + tree = atree; + list = alist; + if (tree->op == op) { + ins: list->nlist[list->nextn++] = tree; + insert(op, tree->tr1, list); + insert(op, tree->tr2, list); + return; + } + tree = optim(tree); + if (tree->op == op) + goto ins; + if (!isfloat(tree)) { + /* c1*(x+c2) -> c1*x+c1*c2 */ + if ((tree->op==TIMES||tree->op==LSHIFT) + && tree->tr2->op==CON && tree->tr2->value>0 + && tree->tr1->op==PLUS && tree->tr1->tr2->op==CON) { + d = tree->tr2->value; + if (tree->op==TIMES) + tree->tr2->value =* tree->tr1->tr2->value; + else + tree->tr2->value = tree->tr1->tr2->value << d; + tree->tr1->tr2->value = d; + tree->tr1->op = tree->op; + tree->op = PLUS; + if (op==PLUS) + goto ins; + } + } + d = degree(tree); + for (i=0; inextl; i++) { + if ((d1=degree(list->llist[i]))llist[i]; + list->llist[i] = tree; + tree = t; + d = d1; + } + } + list->llist[list->nextl++] = tree; +} + +block(an, args) +{ + register int *p; + int *oldp; + register *argp, n; + + oldp = p = spacep; + n = an+3; + argp = &args; + do + *p++ = *argp++; + while (--n); + if (p >= &treespace[ossiz]) { + error("Exp. ov. pass 2"); + exit(1); + } + spacep = p; + return(oldp); +} + +islong(t) +{ + if (t==LONG) + return(2); + return(1); +} + +isconstant(at) +struct tnode *at; +{ + register struct tnode *t; + + t = at; + if (t->op==CON || t->op==SFCON) + return(t); + if (t->op==ITOL && t->tr1->op==CON) + return(t->tr1); + return(0); +} + +hardlongs(at) +struct tnode *at; +{ + register struct tnode *t; + + t = at; + switch(t->op) { + + case TIMES: + case DIVIDE: + case MOD: + t->op =+ LTIMES-TIMES; + break; + + case ASTIMES: + case ASDIV: + case ASMOD: + t->op =+ LASTIMES-ASTIMES; + t->tr1 = block(1, AMPER, LONG+PTR, 0, t->tr1); + break; + + default: + return(t); + } + return(optim(t)); +} diff --git a/usr/source/c/c13.c b/usr/source/c/c13.c new file mode 100644 index 0000000000..49cf6a6280 --- /dev/null +++ b/usr/source/c/c13.c @@ -0,0 +1,227 @@ +int opdope[] { + 000000, /* EOF */ + 000000, /* ; */ + 000000, /* { */ + 000000, /* } */ + 036000, /* [ */ + 002000, /* ] */ + 036000, /* ( */ + 002000, /* ) */ + 014201, /* : */ + 007001, /* , */ + 000000, /* field selection */ + 000000, /* 11 */ + 000000, /* 12 */ + 000000, /* 13 */ + 000000, /* 14 */ + 000000, /* 15 */ + 000000, /* 16 */ + 000000, /* 17 */ + 000000, /* 18 */ + 000000, /* 19 */ + 000400, /* name */ + 000400, /* short constant */ + 000400, /* string */ + 000400, /* float */ + 000400, /* double */ + 000000, /* 25 */ + 000000, /* 26 */ + 000400, /* autoi, *r++ */ + 000400, /* autod, *--r */ + 000000, /* 29 */ + 034203, /* ++pre */ + 034203, /* --pre */ + 034203, /* ++post */ + 034203, /* --post */ + 034220, /* !un */ + 034202, /* &un */ + 034220, /* *un */ + 034200, /* -un */ + 034220, /* ~un */ + 036001, /* . (structure reference) */ + 030101, /* + */ + 030001, /* - */ + 032101, /* * */ + 032001, /* / */ + 032001, /* % */ + 026061, /* >> */ + 026061, /* << */ + 020161, /* & */ + 016161, /* | */ + 016161, /* ^ */ + 036001, /* -> */ + 001000, /* int -> double */ + 001000, /* double -> int */ + 000001, /* && */ + 000001, /* || */ + 030001, /* &~ */ + 001000, /* double -> long */ + 001000, /* long -> double */ + 001000, /* integer -> long */ + 001000, /* long -> integer */ + 022005, /* == */ + 022005, /* != */ + 024005, /* <= */ + 024005, /* < */ + 024005, /* >= */ + 024005, /* > */ + 024005, /*

p */ + 024005, /* >=p */ + 012213, /* =+ */ + 012213, /* =- */ + 012213, /* =* */ + 012213, /* =/ */ + 012213, /* =% */ + 012253, /* =>> */ + 012253, /* =<< */ + 012253, /* =& */ + 012253, /* =| */ + 012253, /* =^ */ + 012213, /* = */ + 030001, /* & for tests */ + 032101, /* * (long) */ + 032001, /* / (long) */ + 032001, /* % (long) */ + 012253, /* =& ~ */ + 012213, /* =* (long) */ + 012213, /* / (long) */ + 012213, /* % (long) */ + 000000, /* 89 */ + 014201, /* ? */ + 026061, /* long << */ + 012253, /* long =<< */ + 000000, /* 93 */ + 000000, /* 94 */ + 000000, /* 95 */ + 000000, /* 96 */ + 000000, /* 97 */ + 000000, /* 98 */ + 000000, /* 99 */ + 036001, /* call */ + 036000, /* mcall */ + 000000, /* goto */ + 000000, /* jump cond */ + 000000, /* branch cond */ + 000400, /* set nregs */ + 000000, /* 106 */ + 000000, /* 107 */ + 000000, /* 108 */ + 000000, /* 109 */ + 000000 /* force r0 */ +}; + +char *opntab[] { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ":", + ",", + "field select", + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + "name", + "short constant", + "string", + "float", + "double", + 0, + 0, + "*r++", + "*--r", + 0, + "++pre", + "--pre", + "++post", + "--post", + "!un", + "&", + "*", + "-", + "~", + ".", + "+", + "-", + "*", + "/", + "%", + ">>", + "<<", + "&", + "|", + "^", + "->", + "int->double", + "double->int", + "&&", + "||", + "&~", + "double->long", + "long->double", + "integer->long", + "long->integer", + "==", + "!=", + "<=", + "<", + ">=", + ">", + "p", + ">=p", + "=+", + "=-", + "=*", + "=/", + "=%", + "=>>", + "=<<", + "=&", + "=|", + "=^", + "=", + "& for tests", + "*", + "/", + "%", + "=& ~", + "=*", + "=/", + "=%", + 0, + "?", + "<<", + "=<<", + 0, + 0, + 0, + 0, + 0, + "call", + "call", + "call", + 0, + "goto", + "jump cond", + "branch cond", + "set nregs", + "load value", + 0, + 0, + 0, + "force register" +}; diff --git a/usr/source/c/c1h.c b/usr/source/c/c1h.c new file mode 100644 index 0000000000..ea972a66ee --- /dev/null +++ b/usr/source/c/c1h.c @@ -0,0 +1,272 @@ +/* + * C pass 2 header + */ + +#define swsiz 200 +#define ossiz 500 + +struct tnode { + int op; + int type; + int degree; + struct tnode *tr1, *tr2; +}; + +struct bnode { + int bop; + struct tnode *btree; + int lbl; + int cond; +}; + +struct tname { + int nop; + int ntype; + int elsize; + char class; + char regno; + int offset; + int nloc; +}; + +/* + * for field selections + */ +struct tsel { + int op; + int type; + int degree; + struct tnode *tr1; + char flen; + char bitoffs; +}; + +struct tconst { + int cop; + int ctype; + int cdeg; + int value; +}; + +struct optab { + char tabdeg1; + char tabtyp1; + char tabdeg2; + char tabtyp2; + char *tabstring; +}; + +struct table { + int tabop; + struct optab *tabp; +}; + +struct instab { + int iop; + char *str1; + char *str2; +}; + +struct swtab { + int swlab; + int swval; +}; + +char maprel[]; +char notrel[]; +int nreg; +int isn; +int namsiz; +int line; +char ascbuf[518]; +int nerror; +struct table cctab[]; +struct table efftab[]; +struct table regtab[]; +struct table sptab[]; +struct table lsptab[]; +struct instab instab[]; +struct instab branchtab[]; +int opdope[]; +char *opntab[]; +int nstack; +int nfloat; +int *spacep; +int treespace[ossiz]; +int eolflg; +struct tconst czero, cone, fczero; + +/* + operators +*/ +#define EOF 0 +#define SEMI 1 +#define LBRACE 2 +#define RBRACE 3 +#define LBRACK 4 +#define RBRACK 5 +#define LPARN 6 +#define RPARN 7 +#define COLON 8 +#define COMMA 9 +#define FSEL 10 + +#define KEYW 19 +#define NAME 20 +#define CON 21 +#define STRING 22 +#define FCON 23 +#define SFCON 24 + +#define AUTOI 27 +#define AUTOD 28 +#define INCBEF 30 +#define DECBEF 31 +#define INCAFT 32 +#define DECAFT 33 +#define EXCLA 34 +#define AMPER 35 +#define STAR 36 +#define NEG 37 +#define COMPL 38 + +#define DOT 39 +#define PLUS 40 +#define MINUS 41 +#define TIMES 42 +#define DIVIDE 43 +#define MOD 44 +#define RSHIFT 45 +#define LSHIFT 46 +#define AND 47 +#define NAND 55 +#define OR 48 +#define EXOR 49 +#define ARROW 50 +#define ITOF 51 +#define FTOI 52 +#define LOGAND 53 +#define LOGOR 54 +#define FTOL 56 +#define LTOF 57 +#define ITOL 58 +#define LTOI 59 + +#define EQUAL 60 +#define NEQUAL 61 +#define LESSEQ 62 +#define LESS 63 +#define GREATEQ 64 +#define GREAT 65 +#define LESSEQP 66 +#define LESSP 67 +#define GREATQP 68 +#define GREATP 69 + +#define ASPLUS 70 +#define ASMINUS 71 +#define ASTIMES 72 +#define ASDIV 73 +#define ASMOD 74 +#define ASRSH 75 +#define ASLSH 76 +#define ASSAND 77 +#define ASOR 78 +#define ASXOR 79 +#define ASSIGN 80 +#define TAND 81 +#define LTIMES 82 +#define LDIV 83 +#define LMOD 84 +#define ASSNAND 85 +#define LASTIMES 86 +#define LASDIV 87 +#define LASMOD 88 + +#define QUEST 90 +#define LLSHIFT 91 +#define ASLSHL 92 +#define CALL1 98 +#define CALL2 99 +#define CALL 100 +#define MCALL 101 +#define JUMP 102 +#define CBRANCH 103 +#define INIT 104 +#define SETREG 105 +#define LOAD 106 +#define RFORCE 110 + +/* + * Intermediate code operators + */ +#define BRANCH 111 +#define LABEL 112 +#define NLABEL 113 +#define RLABEL 114 +#define BDATA 200 +#define WDATA 201 +#define PROG 202 +#define DATA 203 +#define BSS 204 +#define CSPACE 205 +#define SSPACE 206 +#define SYMDEF 207 +#define SAVE 208 +#define RETRN 209 +#define EVEN 210 +#define PROFIL 212 +#define SWIT 213 +#define EXPR 214 +#define SNAME 215 +#define RNAME 216 +#define ANAME 217 +#define NULL 218 + +/* + * types + */ +#define INT 0 +#define CHAR 1 +#define FLOAT 2 +#define DOUBLE 3 +#define STRUCT 4 +#define RSTRUCT 5 +#define LONG 6 + +#define TYLEN 2 +#define TYPE 07 +#define XTYPE (03<<3) +#define PTR 010 +#define FUNC 020 +#define ARRAY 030 + +/* + storage classes +*/ +#define KEYWC 1 +#define MOS 10 +#define AUTO 11 +#define EXTERN 12 +#define STATIC 13 +#define REG 14 +#define STRTAG 15 +#define ARG 16 +#define OFFS 20 +#define XOFFS 21 +#define SOFFS 22 + +/* + Flag bits +*/ + +#define BINARY 01 +#define LVALUE 02 +#define RELAT 04 +#define ASSGOP 010 +#define LWORD 020 +#define RWORD 040 +#define COMMUTE 0100 +#define RASSOC 0200 +#define LEAF 0400 +#define CNVRT 01000 diff --git a/usr/source/c/c1t.s b/usr/source/c/c1t.s new file mode 100644 index 0000000000..8cc6ca6d1f --- /dev/null +++ b/usr/source/c/c1t.s @@ -0,0 +1,85 @@ +/ C operator tables + +.globl fltused; fltused=. +.globl _instab +.globl _branchtab + +.data +_instab: + 80.; 1f; 2f; .text; 1:; 2:; .data + 60.; 1f; 2f; .text; 1: ; 2: ; .data + 106.; 1b; 2b + 61.; 1b; 2b + 62.; 1b; 2b + 63.; 1b; 2b + 64.; 1b; 2b + 65.; 1b; 2b + 66.; 1b; 2b + 67.; 1b; 2b + 68.; 1b; 2b + 69.; 1b; 2b + 40.; 1f; 3f; .text; 1:; .data + 70.; 1b; 3f + 41.; 2f; 4f; .text; 2:; .data + 71.; 2b; 4f + 30.; 1b; 3f; .text; 3:; .data + 31.; 2b; 4f; .text; 4:; .data + 32.; 1b; 3b + 33.; 2b; 4b + 42.; 5f; 5f; .text; 5:; .data + 72.; 5b; 5b + 43.; 6f; 6f; .text; 6:; .data + 73.; 6b; 6b + 44.; 5b; 6b + 74.; 5b; 6b + 45.; 5f; 6f; .text; 6:; .data + 75.; 5f; 6b + 46.; 5f; 6f; .text; 5:; 6:; .data + 76.; 5b; 6b + 47.; 5f; 5f; .text; 5:; 6:; .data + 55.; 5b; 6b + 85.; 5b; 6b + 81.; 5f; 6f; .text; 5:; 6:; .data + 48.; 5f; 6f; .text; 5:; 6:; .data + 78.; 5b; 6b + 49.; 5f; 5f; .text; 5:; .data + 79.; 5b; 5b + 37.; 1f; 1f; .text; 1:; .data + 38.; 1f; 1f; .text; 1:; .data + + 98.; 1f; 1f; .text; 1:<*$\0>; .data + 99.; 1b+2; 1b+2 + 91.; 1f; 1f; .text; 1: ; .data + 92.; 1b; 1b + 82.; 1f; 1f; .text; 1:; .data + 83.; 1f; 1f; .text; 1:; .data + 84.; 1f; 1f; .text; 1:; .data + 86.; 1f; 1f; .text; 1:; .data + 87.; 1f; 1f; .text; 1:; .data + 88.; 1f; 1f; .text; 1:; .data + 0 + +.data +_branchtab: + 60.; 0f; 1f; .text; 0:; 1:; .data + 61.; 1b; 0b + 62.; 2f; 5f; .text; 2:; 5:; .data + 63.; 3f; 4f; .text; 3:; 4:; .data + 64.; 4b; 3b + 65.; 5b; 2b + 66.; 6f; 9f; .text; 6:; 9:; .data + 67.; 7f; 8f; .text; 7:; 8:; .data + 68.; 8b; 7b + 69.; 9b; 6b + + 260.; 0b; 1b + 261.; 1b; 0b + 262.; 2b; 5b + 263.; 3b; 4b + 264.; 4b; 3b + 265.; 5b; 2b + 266.; 0b; 1b + 267.; 7f; 8f; .text; 7:; 8:; .data + 268.; 8b; 7b + 269.; 1b; 0b + 0 diff --git a/usr/source/c/c20.c b/usr/source/c/c20.c new file mode 100644 index 0000000000..d06571fc8b --- /dev/null +++ b/usr/source/c/c20.c @@ -0,0 +1,673 @@ +# +/* + * C object code improver + */ + +#include "c2h.c" + +struct optab optab[] { + "jbr", JBR, + "jeq", CBR | JEQ<<8, + "jne", CBR | JNE<<8, + "jle", CBR | JLE<<8, + "jge", CBR | JGE<<8, + "jlt", CBR | JLT<<8, + "jgt", CBR | JGT<<8, + "jlo", CBR | JLO<<8, + "jhi", CBR | JHI<<8, + "jlos", CBR | JLOS<<8, + "jhis", CBR | JHIS<<8, + "jmp", JMP, + ".globl",EROU, + "mov", MOV, + "clr", CLR, + "com", COM, + "inc", INC, + "dec", DEC, + "neg", NEG, + "tst", TST, + "asr", ASR, + "asl", ASL, + "sxt", SXT, + "cmp", CMP, + "add", ADD, + "sub", SUB, + "bit", BIT, + "bic", BIC, + "bis", BIS, + "mul", MUL, + "ash", ASH, + "xor", XOR, + ".text",TEXT, + ".data",DATA, + ".bss", BSS, + ".even",EVEN, + "movf", MOVF, + "movof",MOVOF, + "movfo",MOVFO, + "addf", ADDF, + "subf", SUBF, + "divf", DIVF, + "mulf", MULF, + "clrf", CLRF, + "cmpf", CMPF, + "negf", NEGF, + "tstf", TSTF, + "cfcc", CFCC, + "sob", SOB, + "jsr", JSR, + ".end", END, + 0, 0}; + +char revbr[] { JNE, JEQ, JGT, JLT, JGE, JLE, JHIS, JLOS, JHI, JLO }; +int isn 20000; + +main(argc, argv) +char **argv; +{ + register int niter, maxiter, isend; + extern end; + extern fin, fout; + int nflag; + + if (argc>1 && argv[1][0]=='+') { + argc--; + argv++; + debug++; + } + if (argc>1 && argv[1][0]=='-') { + argc--; + argv++; + nflag++; + } + if (argc>1) { + if ((fin = open(argv[1], 0)) < 0) { + printf("C2: can't find %s\n", argv[1]); + exit(1); + } + } else + fin = dup(0); + if (argc>2) { + if ((fout = creat(argv[2], 0666)) < 0) { + fout = 1; + printf("C2: can't create %s\n", argv[2]); + exit(1); + } + } else + fout = dup(1); + lasta = firstr = lastr = sbrk(2); + maxiter = 0; + opsetup(); + do { + isend = input(); + movedat(); + niter = 0; + do { + refcount(); + do { + iterate(); + clearreg(); + niter++; + } while (nchange); + comjump(); + rmove(); + } while (nchange || jumpsw()); + addsob(); + output(); + if (niter > maxiter) + maxiter = niter; + lasta = firstr; + } while (isend); + flush(); + fout = 2; + if (nflag) { + printf("%d iterations\n", maxiter); + printf("%d jumps to jumps\n", nbrbr); + printf("%d inst. after jumps\n", iaftbr); + printf("%d jumps to .+2\n", njp1); + printf("%d redundant labels\n", nrlab); + printf("%d cross-jumps\n", nxjump); + printf("%d code motions\n", ncmot); + printf("%d branches reversed\n", nrevbr); + printf("%d redundant moves\n", redunm); + printf("%d simplified addresses\n", nsaddr); + printf("%d loops inverted\n", loopiv); + printf("%d redundant jumps\n", nredunj); + printf("%d common seqs before jmp's\n", ncomj); + printf("%d skips over jumps\n", nskip); + printf("%d sob's added\n", nsob); + printf("%d redundant tst's\n", nrtst); + printf("%d literals eliminated\n", nlit); + printf("%dK core\n", ((lastr+01777)>>10)&077); + flush(); + } + exit(0); +} + +input() +{ + register struct node *p, *lastp; + register int op; + + lastp = &first; + for (;;) { + op = getline(); + switch (op.op) { + + case LABEL: + p = alloc(sizeof first); + if (line[0] == 'L') { + p->combop = LABEL; + p->labno = getnum(line+1); + p->code = 0; + } else { + p->combop = DLABEL; + p->labno = 0; + p->code = copy(line); + } + break; + + case JBR: + case CBR: + case JMP: + case JSW: + p = alloc(sizeof first); + p->combop = op; + if (*curlp=='L' && (p->labno = getnum(curlp+1))) + p->code = 0; + else { + p->labno = 0; + p->code = copy(curlp); + } + break; + + default: + p = alloc(sizeof first); + p->combop = op; + p->labno = 0; + p->code = copy(curlp); + break; + + } + p->forw = 0; + p->back = lastp; + lastp->forw = p; + lastp = p; + p->ref = 0; + if (op==EROU) + return(1); + if (op==END) + return(0); + } +} + +getline() +{ + register char *lp; + register c; + + lp = line; + while (c = getchar()) { + if (c==':') { + *lp++ = 0; + return(LABEL); + } + if (c=='\n') { + *lp++ = 0; + return(oplook()); + } + *lp++ = c; + } + *lp++ = 0; + return(END); +} + +getnum(ap) +char *ap; +{ + register char *p; + register n, c; + + p = ap; + n = 0; + while ((c = *p++) >= '0' && c <= '9') + n = n*10 + c - '0'; + if (*--p != 0) + return(0); + return(n); +} + +output() +{ + register struct node *t; + register struct optab *op; + register int byte; + + t = &first; + while (t = t->forw) switch (t->op) { + + case END: + return; + + case LABEL: + printf("L%d:", t->labno); + continue; + + case DLABEL: + printf("%s:", t->code); + continue; + + default: + if ((byte = t->subop) == BYTE) + t->subop = 0; + for (op = optab; op->opstring!=0; op++) + if (op->opcode == t->combop) { + printf("%s", op->opstring); + if (byte==BYTE) + printf("b"); + break; + } + if (t->code) { + reducelit(t); + printf("\t%s\n", t->code); + } else if (t->op==JBR || t->op==CBR) + printf("\tL%d\n", t->labno); + else + printf("\n"); + continue; + + case JSW: + printf("L%d\n", t->labno); + continue; + + case SOB: + printf("sob %s,L%d\n", t->code, t->labno); + continue; + + case 0: + if (t->code) + printf("%s", t->code); + printf("\n"); + continue; + } +} + +/* + * Notice addresses of the form + * $xx,xx(r) + * and replace them with (pc),xx(r) + * -- Thanx and a tip of the Hatlo hat to Bliss-11. + */ +reducelit(at) +struct node *at; +{ + register char *c1, *c2; + char *c2s; + register struct node *t; + + t = at; + if (*t->code != '$') + return; + c1 = t->code; + while (*c1 != ',') + if (*c1++ == '\0') + return; + c2s = c1; + c1++; + if (*c1=='*') + c1++; + c2 = t->code+1; + while (*c1++ == *c2++); + if (*--c1!='(' || *--c2!=',') + return; + t->code = copy("(pc)", c2s); + nlit++; +} + +copy(ap) +char *ap; +{ + register char *p, *np; + char *onp; + register n; + int na; + + na = nargs(); + p = ap; + n = 0; + if (*p==0) + return(0); + do + n++; + while (*p++); + if (na>1) { + p = (&ap)[1]; + while (*p++) + n++; + } + onp = np = alloc(n); + p = ap; + while (*np++ = *p++); + if (na>1) { + p = (&ap)[1]; + np--; + while (*np++ = *p++); + } + return(onp); +} + +opsetup() +{ + register struct optab *optp, **ophp; + register char *p; + + for (optp = optab; p = optp->opstring; optp++) { + ophp = &ophash[(((p[0]<<3)+(p[1]<<1)+p[2])&077777) % OPHS]; + while (*ophp++) + if (ophp > &ophash[OPHS]) + ophp = ophash; + *--ophp = optp; + } +} + +oplook() +{ + register struct optab *optp; + register char *lp, *op; + static char tmpop[32]; + struct optab **ophp; + + op = tmpop; + for (lp = line; *lp && *lp!=' ' && *lp!='\t';) + *op++ = *lp++; + *op++ = 0; + while (*lp=='\t' || *lp==' ') + lp++; + curlp = lp; + ophp = &ophash[(((tmpop[0]<<3)+(tmpop[1]<<1)+tmpop[2])&077777) % OPHS]; + while (optp = *ophp) { + op = optp->opstring; + lp = tmpop; + while (*lp == *op++) + if (*lp++ == 0) + return(optp->opcode); + if (*lp++=='b' && *lp++==0 && *--op==0) + return(optp->opcode + (BYTE<<8)); + ophp++; + if (ophp >= &ophash[OPHS]) + ophp = ophash; + } + if (line[0]=='L') { + lp = &line[1]; + while (*lp) + if (*lp<'0' || *lp++>'9') + return(0); + curlp = line; + return(JSW); + } + curlp = line; + return(0); +} + +refcount() +{ + register struct node *p, *lp; + static struct node *labhash[LABHS]; + register struct node **hp; + + for (hp = labhash; hp < &labhash[LABHS];) + *hp++ = 0; + for (p = first.forw; p!=0; p = p->forw) + if (p->op==LABEL) { + labhash[p->labno % LABHS] = p; + p->refc = 0; + } + for (p = first.forw; p!=0; p = p->forw) { + if (p->op==JBR || p->op==CBR || p->op==JSW) { + p->ref = 0; + lp = labhash[p->labno % LABHS]; + if (lp==0 || p->labno!=lp->labno) + for (lp = first.forw; lp!=0; lp = lp->forw) { + if (lp->op==LABEL && p->labno==lp->labno) + break; + } + if (lp) { + hp = nonlab(lp)->back; + if (hp!=lp) { + p->labno = hp->labno; + lp = hp; + } + p->ref = lp; + lp->refc++; + } + } + } + for (p = first.forw; p!=0; p = p->forw) + if (p->op==LABEL && p->refc==0 + && (lp = nonlab(p))->op && lp->op!=JSW) + decref(p); +} + +iterate() +{ + register struct node *p, *rp, *p1; + + nchange = 0; + for (p = first.forw; p!=0; p = p->forw) { + if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) { + rp = nonlab(p->ref); + if (rp->op==JBR && rp->labno && p!=rp) { + nbrbr++; + p->labno = rp->labno; + decref(p->ref); + rp->ref->refc++; + p->ref = rp->ref; + nchange++; + } + } + if (p->op==CBR && (p1 = p->forw)->op==JBR) { + rp = p->ref; + do + rp = rp->back; + while (rp->op==LABEL); + if (rp==p1) { + decref(p->ref); + p->ref = p1->ref; + p->labno = p1->labno; + p1->forw->back = p; + p->forw = p1->forw; + p->subop = revbr[p->subop]; + nchange++; + nskip++; + } + } + if (p->op==JBR || p->op==JMP) { + while (p->forw && p->forw->op!=LABEL + && p->forw->op!=EROU && p->forw->op!=END) { + nchange++; + iaftbr++; + if (p->forw->ref) + decref(p->forw->ref); + p->forw = p->forw->forw; + p->forw->back = p; + } + rp = p->forw; + while (rp && rp->op==LABEL) { + if (p->ref == rp) { + p->back->forw = p->forw; + p->forw->back = p->back; + p = p->back; + decref(rp); + nchange++; + njp1++; + break; + } + rp = rp->forw; + } + xjump(p); + p = codemove(p); + } + } +} + +xjump(ap) +{ + register int *p1, *p2, *p3; + int nxj; + + nxj = 0; + p1 = ap; + if ((p2 = p1->ref)==0) + return(0); + for (;;) { + while ((p1 = p1->back) && p1->op==LABEL); + while ((p2 = p2->back) && p2->op==LABEL); + if (!equop(p1, p2) || p1==p2) + return(nxj); + p3 = insertl(p2); + p1->combop = JBR; + p1->ref = p3; + p1->labno = p3->labno; + p1->code = 0; + nxj++; + nxjump++; + nchange++; + } +} + +insertl(ap) +struct node *ap; +{ + register struct node *lp, *op; + + op = ap; + if (op->op == LABEL) { + op->refc++; + return(op); + } + if (op->back->op == LABEL) { + op = op->back; + op->refc++; + return(op); + } + lp = alloc(sizeof first); + lp->combop = LABEL; + lp->labno = isn++; + lp->ref = 0; + lp->code = 0; + lp->refc = 1; + lp->back = op->back; + lp->forw = op; + op->back->forw = lp; + op->back = lp; + return(lp); +} + +codemove(ap) +struct node *ap; +{ + register struct node *p1, *p2, *p3; + struct node *t, *tl; + int n; + + p1 = ap; + if (p1->op!=JBR || (p2 = p1->ref)==0) + return(p1); + while (p2->op == LABEL) + if ((p2 = p2->back) == 0) + return(p1); + if (p2->op!=JBR && p2->op!=JMP) + goto ivloop; + p2 = p2->forw; + p3 = p1->ref; + while (p3) { + if (p3->op==JBR || p3->op==JMP) { + if (p1==p3) + return(p1); + ncmot++; + nchange++; + p1->back->forw = p2; + p1->forw->back = p3; + p2->back->forw = p3->forw; + p3->forw->back = p2->back; + p2->back = p1->back; + p3->forw = p1->forw; + decref(p1->ref); + return(p2); + } else + p3 = p3->forw; + } + return(p1); +ivloop: + if (p1->forw->op!=LABEL) + return(p1); + p3 = p2 = p2->forw; + n = 16; + do { + if ((p3 = p3->forw) == 0 || p3==p1 || --n==0) + return(p1); + } while (p3->op!=CBR || p3->labno!=p1->forw->labno); + do + if ((p1 = p1->back) == 0) + return(ap); + while (p1!=p3); + p1 = ap; + tl = insertl(p1); + p3->subop = revbr[p3->subop]; + decref(p3->ref); + p2->back->forw = p1; + p3->forw->back = p1; + p1->back->forw = p2; + p1->forw->back = p3; + t = p1->back; + p1->back = p2->back; + p2->back = t; + t = p1->forw; + p1->forw = p3->forw; + p3->forw = t; + p2 = insertl(p1->forw); + p3->labno = p2->labno; + p3->ref = p2; + decref(tl); + if (tl->refc<=0) + nrlab--; + loopiv++; + nchange++; + return(p3); +} + +comjump() +{ + register struct node *p1, *p2, *p3; + + for (p1 = first.forw; p1!=0; p1 = p1->forw) + if (p1->op==JBR && (p2 = p1->ref) && p2->refc > 1) + for (p3 = p1->forw; p3!=0; p3 = p3->forw) + if (p3->op==JBR && p3->ref == p2) + backjmp(p1, p3); +} + +backjmp(ap1, ap2) +struct node *ap1, *ap2; +{ + register struct node *p1, *p2, *p3; + + p1 = ap1; + p2 = ap2; + for(;;) { + while ((p1 = p1->back) && p1->op==LABEL); + p2 = p2->back; + if (equop(p1, p2)) { + p3 = insertl(p1); + p2->back->forw = p2->forw; + p2->forw->back = p2->back; + p2 = p2->forw; + decref(p2->ref); + p2->labno = p3->labno; + p2->ref = p3; + nchange++; + ncomj++; + } else + return; + } +} diff --git a/usr/source/c/c21.c b/usr/source/c/c21.c new file mode 100644 index 0000000000..a423f3a9a0 --- /dev/null +++ b/usr/source/c/c21.c @@ -0,0 +1,659 @@ +# +/* + * C object code improver-- second part + */ + +#include "c2h.c" + +rmove() +{ + register struct node *p; + register char *cp; + register int r; + int r1, flt; + + for (p=first.forw; p!=0; p = p->forw) { + if (debug) { + for (r=0; r<2*NREG; r++) + if (regs[r][0]) + printf("%d: %s\n", r, regs[r]); + printf("-\n"); + } + flt = 0; + switch (p->op) { + + case MOVF: + case MOVFO: + case MOVOF: + flt = NREG; + + case MOV: + if (p->subop==BYTE) + goto badmov; + dualop(p); + if ((r = findrand(regs[RT1], flt)) >= 0) { + if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR) { + p->forw->back = p->back; + p->back->forw = p->forw; + redunm++; + continue; + } + } + repladdr(p, 0, flt); + r = isreg(regs[RT1]); + r1 = isreg(regs[RT2]); + dest(regs[RT2], flt); + if (r >= 0) + if (r1 >= 0) + savereg(r1+flt, regs[r+flt]); + else + savereg(r+flt, regs[RT2]); + else + if (r1 >= 0) + savereg(r1+flt, regs[RT1]); + else + setcon(regs[RT1], regs[RT2]); + source(regs[RT1]); + setcc(regs[RT2]); + continue; + + case ADDF: + case SUBF: + case DIVF: + case MULF: + flt = NREG; + + case ADD: + case SUB: + case BIC: + case BIS: + case MUL: + case DIV: + case ASH: + badmov: + dualop(p); + repladdr(p, 0, flt); + source(regs[RT1]); + dest(regs[RT2], flt); + if (p->op==DIV && (r = isreg(regs[RT2])>=0)) + regs[r+1][0] = 0; + ccloc[0] = 0; + continue; + + case CLRF: + case NEGF: + flt = NREG; + + case CLR: + case COM: + case INC: + case DEC: + case NEG: + case ASR: + case ASL: + case SXT: + singop(p); + dest(regs[RT1], flt); + if (p->op==CLR && flt==0) + if ((r = isreg(regs[RT1])) >= 0) + savereg(r, "$0"); + else + setcon("$0", regs[RT1]); + setcc(regs[RT1]); + continue; + + case TSTF: + flt = NREG; + + case TST: + singop(p); + repladdr(p, 0, flt); + source(regs[RT1]); + if (equstr(regs[RT1], ccloc)) { + p->back->forw = p->forw; + p->forw->back = p->back; + p = p->back; + nrtst++; + nchange++; + } + continue; + + case CMPF: + flt = NREG; + + case CMP: + case BIT: + dualop(p); + source(regs[RT1]); + source(regs[RT2]); + repladdr(p, 1, flt); + ccloc[0] = 0; + continue; + + case CBR: + case CFCC: + ccloc[0] = 0; + continue; + + case JBR: + redunbr(p); + + default: + clearreg(); + } + } +} + +jumpsw() +{ + register struct node *p, *p1; + register t; + int nj; + + t = 0; + nj = 0; + for (p=first.forw; p!=0; p = p->forw) + p->refc = ++t; + for (p=first.forw; p!=0; p = p1) { + p1 = p->forw; + if (p->op == CBR && p1->op==JBR && p->ref && p1->ref + && abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) { + p->subop = revbr[p->subop]; + t = p1->ref; + p1->ref = p->ref; + p->ref = t; + t = p1->labno; + p1->labno = p->labno; + p->labno = t; + nrevbr++; + nj++; + } + } + return(nj); +} + +addsob() +{ + register struct node *p, *p1; + + for (p = &first; (p1 = p->forw)!=0; p = p1) { + if (p->op==DEC && isreg(p->code)>=0 + && p1->combop==(CBR|JNE<<8)) { + if (p->refc < p1->ref->refc) + continue; + if (p->refc - p1->ref->refc > 50) + continue; + p->labno = p1->labno; + p->combop = SOB; + p1->forw->back = p; + p->forw = p1->forw; + nsob++; + } + } +} + +abs(x) +{ + return(x<0? -x: x); +} + +equop(ap1, p2) +struct node *ap1, *p2; +{ + register char *cp1, *cp2; + register struct node *p1; + + p1 = ap1; + if (p1->combop != p2->combop) + return(0); + if (p1->op>0 && p1->opcode; + cp2 = p2->code; + if (cp1==0 && cp2==0) + return(1); + if (cp1==0 || cp2==0) + return(0); + while (*cp1 == *cp2++) + if (*cp1++ == 0) + return(1); + return(0); +} + +decref(ap) +{ + register struct node *p; + + p = ap; + if (--p->refc <= 0) { + nrlab++; + p->back->forw = p->forw; + p->forw->back = p->back; + } +} + +nonlab(ap) +struct node *ap; +{ + register struct node *p; + + p = ap; + while (p && p->op==LABEL) + p = p->forw; + return(p); +} + +alloc(an) +{ + register int n; + register char *p; + + n = an; + n++; + n =& ~01; + if (lasta+n >= lastr) { + if (sbrk(2000) == -1) { + write(2, "Optimizer: out of space\n", 14); + exit(1); + } + lastr =+ 2000; + } + p = lasta; + lasta =+ n; + return(p); +} + +clearreg() +{ + register int i; + + for (i=0; i<2*NREG; i++) + regs[i][0] = '\0'; + conloc[0] = 0; + ccloc[0] = 0; +} + +savereg(ai, as) +char *as; +{ + register char *p, *s, *sp; + + sp = p = regs[ai]; + s = as; + if (source(s)) + return; + while (*p++ = *s) { + if (s[0]=='(' && s[1]=='r' && s[2]<'5') { + *sp = 0; + return; + } + if (*s++ == ',') + break; + } + *--p = '\0'; +} + +dest(as, flt) +char *as; +{ + register char *s; + register int i; + + s = as; + if ((i = isreg(s)) >= 0) + regs[i+flt][0] = 0; + while ((i = findrand(s, flt)) >= 0) + regs[i][0] = 0; + while (*s) { + if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') { + for (i=flt; icode; + p2 = regs[RT1]; + while (*p2++ = *p1++); + regs[RT2][0] = 0; +} + + +dualop(ap) +struct node *ap; +{ + register char *p1, *p2; + register struct node *p; + + p = ap; + p1 = p->code; + p2 = regs[RT1]; + while (*p1 && *p1!=',') + *p2++ = *p1++; + *p2++ = 0; + p2 = regs[RT2]; + *p2 = 0; + if (*p1++ !=',') + return; + while (*p2++ = *p1++); +} + +findrand(as, flt) +char *as; +{ + register int i; + for (i = flt; i='0' && s[1]<='4' && s[2]==0) + return(s[1]-'0'); + return(-1); +} + +check() +{ + register struct node *p, *lp; + + lp = &first; + for (p=first.forw; p!=0; p = p->forw) { + if (p->back != lp) + abort(); + lp = p; + } +} + +source(ap) +char *ap; +{ + register char *p1, *p2; + + p1 = ap; + p2 = p1; + if (*p1==0) + return(0); + while (*p2++); + if (*p1=='-' && *(p1+1)=='(' + || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='(' + || *(p2-2)=='+') { + while (*p1 && *p1++!='r'); + if (*p1>='0' && *p1<='4') + regs[*p1 - '0'][0] = 0; + return(1); + } + return(0); +} + +repladdr(p, f, flt) +struct node *p; +{ + register r; + int r1; + register char *p1, *p2; + static char rt1[50], rt2[50]; + + if (f) + r1 = findrand(regs[RT2], flt); + else + r1 = -1; + r = findrand(regs[RT1], flt); + if (r1 >= NREG) + r1 =- NREG; + if (r >= NREG) + r =- NREG; + if (r>=0 || r1>=0) { + p2 = regs[RT1]; + for (p1 = rt1; *p1++ = *p2++;); + if (regs[RT2][0]) { + p1 = rt2; + *p1++ = ','; + for (p2 = regs[RT2]; *p1++ = *p2++;); + } else + rt2[0] = 0; + if (r>=0) { + rt1[0] = 'r'; + rt1[1] = r + '0'; + rt1[2] = 0; + nsaddr++; + } + if (r1>=0) { + rt2[1] = 'r'; + rt2[2] = r1 + '0'; + rt2[3] = 0; + nsaddr++; + } + p->code = copy(rt1, rt2); + } +} + +movedat() +{ + register struct node *p1, *p2; + struct node *p3; + register seg; + struct node data; + struct node *datp; + + if (first.forw == 0) + return; + datp = &data; + for (p1 = first.forw; p1!=0; p1 = p1->forw) { + if (p1->op == DATA) { + p2 = p1->forw; + while (p2 && p2->op!=TEXT) + p2 = p2->forw; + if (p2==0) + break; + p3 = p1->back; + p1->back->forw = p2->forw; + p2->forw->back = p3; + p2->forw = 0; + datp->forw = p1; + p1->back = datp; + p1 = p3; + datp = p2; + } + } + if (data.forw) { + datp->forw = first.forw; + first.forw->back = datp; + data.forw->back = &first; + first.forw = data.forw; + } + seg = -1; + for (p1 = first.forw; p1!=0; p1 = p1->forw) { + if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) { + if (p1->op == seg || p1->forw&&p1->forw->op==seg) { + p1->back->forw = p1->forw; + p1->forw->back = p1->back; + p1 = p1->back; + continue; + } + seg = p1->op; + } + } +} + +redunbr(ap) +struct node *ap; +{ + register struct node *p, *p1; + register char *ap1; + char *ap2; + + if ((p1 = p->ref) == 0) + return; + p1 = nonlab(p1); + if (p1->op==TST) { + singop(p1); + savereg(RT2, "$0"); + } else if (p1->op==CMP) + dualop(p1); + else + return; + if (p1->forw->op!=CBR) + return; + ap1 = findcon(RT1); + ap2 = findcon(RT2); + p1 = p1->forw; + if (compare(p1->subop, ap1, ap2)) { + nredunj++; + nchange++; + decref(p->ref); + p->ref = p1->ref; + p->labno = p1->labno; + p->ref->refc++; + } +} + +findcon(i) +{ + register char *p; + register r; + + p = regs[i]; + if (*p=='$') + return(p); + if ((r = isreg(p)) >= 0) + return(regs[r]); + if (equstr(p, conloc)) + return(conval); + return(p); +} + +compare(op, acp1, acp2) +char *acp1, *acp2; +{ + register char *cp1, *cp2; + register n1; + int n2; + struct { int i;}; + + cp1 = acp1; + cp2 = acp2; + if (*cp1++ != '$' || *cp2++ != '$') + return(0); + n1 = 0; + while (*cp2 >= '0' && *cp2 <= '7') { + n1 =<< 3; + n1 =+ *cp2++ - '0'; + } + n2 = n1; + n1 = 0; + while (*cp1 >= '0' && *cp1 <= '7') { + n1 =<< 3; + n1 =+ *cp1++ - '0'; + } + if (*cp1=='+') + cp1++; + if (*cp2=='+') + cp2++; + do { + if (*cp1++ != *cp2) + return(0); + } while (*cp2++); + cp1 = n1; + cp2 = n2; + switch(op) { + + case JEQ: + return(cp1 == cp2); + case JNE: + return(cp1 != cp2); + case JLE: + return(cp1.i <= cp2.i); + case JGE: + return(cp1.i >= cp2.i); + case JLT: + return(cp1.i < cp2.i); + case JGT: + return(cp1.i > cp2.i); + case JLO: + return(cp1 < cp2); + case JHI: + return(cp1 > cp2); + case JLOS: + return(cp1 <= cp2); + case JHIS: + return(cp1 >= cp2); + } + return(0); +} + +setcon(ar1, ar2) +char *ar1, *ar2; +{ + register char *cl, *cv, *p; + + cl = ar2; + cv = ar1; + if (*cv != '$') + return; + if (!natural(cl)) + return; + p = conloc; + while (*p++ = *cl++); + p = conval; + while (*p++ = *cv++); +} + +equstr(ap1, ap2) +char *ap1, *ap2; +{ + char *p1, *p2; + + p1 = ap1; + p2 = ap2; + do { + if (*p1++ != *p2) + return(0); + } while (*p2++); + return(1); +} + +setcc(ap) +char *ap; +{ + register char *p, *p1; + + p = ap; + if (!natural(p)) { + ccloc[0] = 0; + return; + } + p1 = ccloc; + while (*p1++ = *p++); +} + +natural(ap) +char *ap; +{ + register char *p; + + p = ap; + if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(') + return(0); + while (*p++); + p--; + if (*--p == '+' || *p ==')' && *--p != '5') + return(0); + return(1); +} diff --git a/usr/source/c/c2h.c b/usr/source/c/c2h.c new file mode 100644 index 0000000000..3f37a00768 --- /dev/null +++ b/usr/source/c/c2h.c @@ -0,0 +1,125 @@ +/* + * Header for object code improver + */ + +#define JBR 1 +#define CBR 2 +#define JMP 3 +#define LABEL 4 +#define DLABEL 5 +#define EROU 7 +#define JSW 9 +#define MOV 10 +#define CLR 11 +#define COM 12 +#define INC 13 +#define DEC 14 +#define NEG 15 +#define TST 16 +#define ASR 17 +#define ASL 18 +#define SXT 19 +#define CMP 20 +#define ADD 21 +#define SUB 22 +#define BIT 23 +#define BIC 24 +#define BIS 25 +#define MUL 26 +#define DIV 27 +#define ASH 28 +#define XOR 29 +#define TEXT 30 +#define DATA 31 +#define BSS 32 +#define EVEN 33 +#define MOVF 34 +#define MOVOF 35 +#define MOVFO 36 +#define ADDF 37 +#define SUBF 38 +#define DIVF 39 +#define MULF 40 +#define CLRF 41 +#define CMPF 42 +#define NEGF 43 +#define TSTF 44 +#define CFCC 45 +#define SOB 46 +#define JSR 47 +#define END 48 + +#define JEQ 0 +#define JNE 1 +#define JLE 2 +#define JGE 3 +#define JLT 4 +#define JGT 5 +#define JLO 6 +#define JHI 7 +#define JLOS 8 +#define JHIS 9 + +#define BYTE 100 + +struct node { + char op; + char subop; + struct node *forw; + struct node *back; + struct node *ref; + int labno; + char *code; + int refc; +}; + +struct { + int combop; +}; + +struct optab { + char *opstring; + int opcode; +} optab[]; + +char line[512]; +struct node first; +char *curlp; +int nbrbr; +int nsaddr; +int redunm; +int iaftbr; +int njp1; +int nrlab; +int nxjump; +int ncmot; +int nrevbr; +int loopiv; +int nredunj; +int nskip; +int ncomj; +int nsob; +int nrtst; +int nlit; + +int nchange; +int isn; +int debug; +char *lasta; +char *lastr; +char *firstr; +char revbr[]; +char regs[12][20]; +char conloc[20]; +char conval[20]; +char ccloc[20]; + +#define RT1 10 +#define RT2 11 +#define FREG 5 +#define NREG 5 +#define LABHS 127 +#define OPHS 57 + +struct optab *ophash[OPHS]; +struct { char lbyte; }; diff --git a/usr/source/c/cvopt.c b/usr/source/c/cvopt.c new file mode 100644 index 0000000000..5b1c3d66b4 --- /dev/null +++ b/usr/source/c/cvopt.c @@ -0,0 +1,370 @@ +int nofloat; +int peekc; +int obuf[259]; +int tabflg; +int labno 1; + +main(argc, argv) +char **argv; +{ +/* + A1 -> A + A2 B + A O + B1 C + B2 D + BE L + BF P + C1 E + C2 F + F G + H H + R I + R1 J + S K + I M + M N + + * +1 + S +2 + C +4 + 1 +8 + + z -> 4 + c 10 + a 14 + e 20 + n 63 + * +0100 +*/ + + auto c,snlflg,nlflg,t,smode,m,ssmode; + extern fin; + + smode = nlflg = snlflg = ssmode = 0; + if (argc>1) + if ((fin = open(argv[1], 0)) < 0) { + putchar('?\n'); + return; + } + obuf[0] = 1; + if (argc>2) + if ((obuf[0] = creat(argv[2], 0666)) < 0) { + putchar('?\n'); + return; + } +loop: + c = getc(); + if (c!='\n' && c!='\t') nlflg = 0; + if (ssmode!=0 && c!='%') { + ssmode = 0; + printf(".data\nL%d:<", labno++); + } + switch(c) { + + case '\0': + printf(".text; 0\n"); + fflush(obuf); + return; + + case ':': + if (!smode) + printf("=.+2; 0"); else + putchar(':'); + goto loop; + + case 'A': + if ((c=getc())=='1' || c=='2') { + putchar(c+'A'-'1'); + goto loop; + } + putchar('O'); + peekc = c; + goto loop; + + case 'B': + switch (getc()) { + + case '1': + putchar('C'); + goto loop; + + case '2': + putchar('D'); + goto loop; + + case 'E': + putchar('L'); + goto loop; + + case 'F': + putchar('P'); + goto loop; + } + putchar('?'); + goto loop; + + case 'C': + putchar(getc()+'E'-'1'); + goto loop; + + case 'F': + putchar('G'); + goto subtre; + + case 'R': + if ((c=getc()) == '1') + putchar('J'); else { + putchar('I'); + peekc = c; + } + goto loop; + + case 'H': + putchar('H'); + goto subtre; + + case 'I': + putchar('M'); + goto loop; + + case 'S': + putchar('K'); +subtre: + snlflg = 1; + t = 'A'; +l1: + switch (c=getc()) { + + case '*': + t++; + goto l1; + + case 'S': + t =+ 2; + goto l1; + + case 'C': + t =+ 4; + goto l1; + + case '1': + t =+ 8; + goto l1; + + case '2': + t =+ 16; + goto l1; + } + peekc = c; + putchar(t); + goto loop; + + case '#': + if(getc()=='1') + putchar('#'); else + putchar('"'); + goto loop; + + case '%': + if (smode) + printf(".text;"); + if (ssmode==0) { + if ((peekc=getc())=='[') { + peekc = 0; + printf(".data;"); + while((c=getc())!=']') + putchar(c); + getc(); + printf(";.text;"); + goto loop; + } + } +loop1: + switch (c=getc()) { + + case ' ': + case '\t': + goto loop1; + case 'a': + m = 16; + t = flag(); + goto pf; + + case ',': + putchar(';'); + goto loop1; + + case 'i': + m = 12; + t = flag(); + goto pf; + case 'z': + m = 4; + t = flag(); + goto pf; + + case 'r': + m = 9; + t = flag(); + goto pf; + + case '1': + m = 5; + t = flag(); + goto pf; + + case 'c': + t = 0; + m = 8; + goto pf; + + case 'e': + t = flag(); + m = 20; + goto pf; + + case 'n': + t = flag(); + m = 63; +pf: + if ((c=getc())=='*') + m =+ 0100; else + peekc = c; + printf(".byte %o,%o", m, t); + goto loop1; + case '[': + printf("L%d=", labno++); + while ((c=getc())!=']') + putchar(c); + ssmode = 0; + smode = 0; + goto loop; + + case '\n': + printf("\nL%d\n", labno); + ssmode = 1; + nlflg = 1; + smode = 1; + goto loop; + } + putchar(c); + goto loop1; + + case '\t': + if (nlflg) { + nlflg = 0; + goto loop; + } + if (smode) { + tabflg++; + goto loop; + } + putchar('\t'); + goto loop; + + case '\n': + if (!smode) { + putchar('\n'); + goto loop; + } + if (nlflg) { + nlflg = 0; + printf("\\0>\n.text\n"); + smode = 0; + goto loop; + } + if (!snlflg) + printf("\\n"); + snlflg = 0; + printf(">\n<"); + nlflg = 1; + goto loop; + + case 'X': + case 'Y': + case 'T': + snlflg++; + } + putchar(c); + goto loop; +} + +getc() { + auto t, ifcnt; + + ifcnt = 0; +gc: + if (peekc) { + t = peekc; + peekc = 0; + } else + t = getchar(); + if (t==0) + return(0); + if (t=='{') { + ifcnt++; + t = getchar(); + } + if (t=='}') { + t = getc(); + if (--ifcnt==0) + if (t=='\n') + t = getc(); + } + if (ifcnt && nofloat) + goto gc; + return(t); +} + +flag() { + register c, f; + + f = 0; +l1: + switch(c=getc()) { + + case 'w': + f = 1; + goto l1; + + case 'i': + f = 2; + goto l1; + + case 'b': + f = 3; + goto l1; + + case 'f': + f = 4; + goto l1; + + case 'd': + f = 5; + goto l1; + + case 's': + f = 6; + goto l1; + + case 'l': + f = 8; + goto l1; + + case 'p': + f =+ 16; + goto l1; + } + peekc = c; + return(f); +} + +putchar(c) +{ + if (tabflg) { + tabflg = 0; + printf(">;.byte %o;<", c+0200); + } else + putc(c, obuf); +} diff --git a/usr/source/c/table.s b/usr/source/c/table.s new file mode 100644 index 0000000000..748563fa4f --- /dev/null +++ b/usr/source/c/table.s @@ -0,0 +1,1255 @@ +/ +/ c code tables-- compile to register +/ + +.globl _regtab + +.data +_regtab=. + 106.; cr106 + 30.; cr70 + 31.; cr70 + 32.; cr32 + 33.; cr32 + 37.; cr37 + 38.; cr37 + 98.; cr100 + 99.; cr100 + 80.; cr80 + 40.; cr40 + 41.; cr40 / - like + + 42.; cr42 + 43.; cr43 + 44.; cr43 + 45.; cr45 + 46.; cr40 + 55.; cr40 + 48.; cr40 + 49.; cr49 + 70.; cr70 + 71.; cr70 + 72.; cr72 + 73.; cr73 + 74.; cr74 + 75.; cr75 + 76.; cr72 + 78.; cr70 + 85.; cr70 + 79.; cr79 + 102.; cr102 + 51.; cr51 + 52.; cr52 + 56.; cr56 + 57.; cr57 + 58.; cr58 + 59.; cr59 + 91.; cr91 + 82.; cr82 + 83.; cr82 + 84.; cr82 + 86.; cr86 + 87.; cr86 + 88.; cr86 + 0 +.text + +/ goto +cr102: +%a,n + jmp A1 + +%n*,n + F* + jmp #1(R) + +/ call +cr100: +%a,n + jsr pc,IA1 + +%n*,n + F* + jsr pc,#1(R) + +%n,n + F + jsr pc,(R) + +/ addressible +cr106: +%z,n + clr R + +%zf,n + clrf R + +%a,n +%ad,n + movB1 A1,R + +%af,n + movof A1,R + +%n*,n +%nd*,n + F* + movB1 #1(R),R + +%nf*,n + F* + movof #1(R),R + +%al,n + mov A1+,R+ + mov A1,R + +%nl*,n + F* + mov #1+2(R),R+ + mov #1(R),R + +/ ++,-- postfix +cr32: +%a,1 + movB1 A1',R + I'B1 A1 + +%aw,n + mov A1',R + I A2,A1 + +%e*,1 + F1* + movB1 #1(R1),R + I'B1 #1(R1) + +%n*,1 + F* + movB1 #1(R),-(sp) + I'B1 #1(R) + movB1 (sp)+,R + +%ew*,n + F1* + mov #1(R1),R + I A2,#1(R1) + +%nw*,n + F* + mov #1(R),-(sp) + I A2,#1(R) + mov (sp)+,R + +%al,1 + F + I $1,A1+ + V A1 + +%el*,1 + F1* + mov #1+2(R1),R+ + mov #1(R1),R + I $1,#1+2(R1) + V #1(R1) + +%nl*,1 + F* + mov #1+2(R),-(sp) + mov #1(R),-(sp) + add $1,#1+2(R) + V #1(R) + mov (sp)+,R + mov (sp)+,R+ + +/ - unary, ~ +cr37: +%n,n +%nf,n + F + IBF R + +%nl,n + F + I R + I R+ + V R + +/ = +cr80: +%a,n +%ad,nf + S + movB1 R,A1 + +%af,nf + S + movfo R,A1 + +%nd*,af + F* + S + movf R,#1(R) + +%n*,a + F* + movB1 A2,#1(R) + movB1 #1(R),R + +%nf*,af + F* + S + movfo R,#1(R) + +%n*,e + F* + S1 + movB1 R1,#1(R) + movB1 R1,R + +%ed*,nf + S + F1* + movf R,#1(R1) + +%ef*,nf + S + F1* + movfo R,#1(R1) + +%n*,n +%nd*,nf + FS* + S + movB1 R,*(sp)+ + +%nf*,nf + FS* + S + movfo R,*(sp)+ + +/ +, -, |, &~, << +cr40: +%n,z + F + +%n,1 + F + I' R + +%[add1:] +%n,aw +%nf,ad + F + IB2 A2,R + +%[add2:] +%n,ew* +%nf,ed* + F + S1* + IB2 #2(R1),R + +%[add3:] +%n,e +%nf,ef + F + S1 + IBF R1,R + +%[add4:] +%n,nw* +%nf,nd* + SS* + F + IB2 *(sp)+,R + +%[add5:] +%n,n +%nf,nf + SS + F + IBF (sp)+,R + +%nl,c + F + I A2,R+ + V R + +%nl,al + F + I A2,R + I A2+,R+ + V R + +%nl,el + F + S1 + I R1+,R+ + V R + I R1,R + +%nl,nl + SS + F + I (sp)+,R + I (sp)+,R+ + V R + +/ ^ -- xor +cr49: +%n,e +% [add3] + +%n,n + FS + S + xor R,(sp) + mov (sp)+,R + +/ >> (all complicated cases taken care of by << -) +cr45: +%n,1 + F + asr R + +/ * -- R must be odd on integers +cr42: +%n,aw +%nf,ad +% [add1] + +%n,ew* +%nf,ed* +% [add2] + +%n,e +%nf,ef +% [add3] + +%n,n +%nf,nf +% [add5] + +/ / R must be odd on integers +cr43: +%n,aw + F + T + sxt R- + div A2,R- + +%n,ew* + F + T + sxt R- + S1* + div #2(R1),R- + +%n,e + F + T + sxt R- + S1 + div R1,R- + +%n,n + SS + F + T + sxt R- + div (sp)+,R- + +%nf,ad +% [add1] + +%nf,ed* +% [add2] + +%nf,ef +% [add3] + +%nf,nf +% [add5] + +/ =+, =-, =|, =&~ +cr70: +%[addq1:] +%aw,aw + I A2,A1' + mov A1,R + +%[addq1a:] +%a,aw +%ad,ad + movB1 A1',R + IBF A2,R + movB1 R,A1 + +%[addq2:] +%aw,nw* + S* + I #2(R),A1' + mov A1,R + +%[addq3:] +%aw,n + S + I R,A1' + mov A1,R + +%[addq4:] +%ew*,nw* + S* + F1* + I #2(R),#1(R1) + mov #1(R1),R + +%[addq4a:] +%ad,ef + movf A1',R + S1 + IBF R1,R + movf R,A1 + +%[addq5:] +%a,n +%ad,nf + SS + movB1 A1',R + IBF (sp)+,R + movB1 R,A1 + +%[addq6:] +%af,nf + SS + movof A1',R + IBF (sp)+,R + movfo R,A1 + +%[addq7:] +%ew*,n + S + F1* + I R,#1(R1) + mov #1(R1),R + +%[addq8:] +%nw*,n + SS + F* + I (sp)+,#1(R) + mov #1(R),R + +%[addq9:] +%n*,n + FS* + SS + movB1 *2(sp),R + IBF (sp)+,R + movB1 R,*(sp)+ + +%[addq9a:] +%nd*,nf + SS + F* + movB1 #1(R),R + IBF (sp)+,R + movB1 R,#1(R) + +%[addq10:] +%nf*,nf + SS + F* + movof #1(R),R1 + IBF (sp)+,R1 + movfo R1,#1(R) + movf R1,R + +/ =*, =<< (for integer multiply, R must be odd) +cr72: +%a,aw +%ad,ad +% [addq1a] + +%af,nf +% [addq6] + +%ad,ef +% [addq4a] + +%a,n +%ad,nf +% [addq5] + +%n*,n +% [addq9] + +%nd*,nf +% [addq9a] + +%nf*,nf +% [addq10] + +/ =/ ; R must be odd on integers +cr73: +%a,aw + movB1 A1',R + sxt R- + divBF A2,R- + movB1 R-,A1 + +%a,n + SS + movB1 A1',R + sxt R- + div (sp)+,R- + movB1 R-,A1 + +%e*,n + SS + F1* + movB1 #1(R1),R + sxt R- + div (sp)+,R- + movB1 R-,#1(R1) + +%n*,n + FS* + SS + movB1 *2(sp),R + sxt R- + div (sp)+,R- + movB1 R-,*(sp)+ + +%ad,ad +% [addq1a] + +%ad,ef +% [addq4a] + +%ad,nf +% [addq5] + +%af,nf +% [addq6] + +%nd*,nf +% [addq9a] + +%nf*,nf +% [addq10] + +/ =mod; R must be odd on integers +cr74: +%a,aw + movB1 A1',R + sxt R- + div A2,R- + movB1 R,A1 + +%a,n + SS + movB1 A1',R + sxt R- + div (sp)+,R- + movB1 R,A1 + +%e*,n + SS + F1* + movB1 #1(R1),R + sxt R- + div (sp)+,R- + movB1 R,#1(R1) + +%n*,n + FS* + SS + movB1 *2(sp),R + sxt R- + div (sp)+,R- + mov R,*(sp)+ + +/ =^ -- =xor +cr79: +%aw,n +% [addq3] + +%ab,n + SS + movb A1',R + xor R,(sp) + mov (sp)+,R + movb R,A1 + +%n*,n + FS* + movB1 *(sp),-(sp) + S + xor R,(sp) + movB1 (sp)+,R + movB1 R,*(sp)+ + +/ =>> (all complicated cases done by =<< -) +cr75: +%a,1 + asrB1 A1' + movB1 A1,R + +%n*,1 + F* + asrB1 #1(R) + movB1 #1(R),R + +/ << for longs +cr91: +%nl,aw +% [add1] + +%nl,ew* +% [add2] + +%nl,e +% [add3] + +%nl,nw* +% [add4] + +%nl,n +% [add5] + +/ int -> float +cr51: +%aw,n + movif A1,R + +%nw*,n + F* + movif #1(R),R + +%n,n + F + movif R,R + +/ float, double -> int +cr52: +%nf,n + F + movfi R,R + +/ double (float) to long +cr56: +%nf,n + F + setl + movfi R,-(sp) + mov (sp)+,R + mov (sp)+,R+ + seti + +/ long to double +cr57: +%al,n + setl + movif A1,R + seti + +%nl*,n + F* + setl + movif #1(R),R + seti + +%nl,n + FS + setl + movif (sp)+,R + seti + +/ integer to long +cr58: +%n,n + F1! + sxt R + +/ long to integer +cr59: +%al,n + mov A1+,R + +%nl*,n + F* + mov #1+2(R),R + +%nl,n + F + mov R+,R + +/ *, /, remainder for longs. +cr82: +%nl,nl + SS + FS + jsr pc,I + add $10,sp + +/ =*, =/, =rem for longs +/ Operands of the form &x op y, so stack space is known. +cr86: +%n,nl + SS + FS + jsr pc,I + add $6,sp + +/ +/ c code tables -- compile for side effects. +/ Also set condition codes properly (except for ++, --) +/ + +.globl _efftab + +.data +_efftab=. + 30.; ci70 + 31.; ci70 + 32.; ci70 + 33.; ci70 + 80.; ci80 + 70.; ci70 + 71.; ci70 / - like + + 78.; ci78 + 85.; ci78 + 75.; ci75 + 76.; ci76 + 92.; ci92 + 0 +.text + +/ = +ci80: +%[move1:] +%a,z +%ad,zf + I'B1 A1 + +%[move2:] +%n*,z +%nd*,zf + F* + I'B1 #1(R) + +%[move3:] +%a,aw +%ab,a + IBE A2,A1 + +%[move4:] +%ab,n* +%a,nw* + S* + IBE #2(R),A1 + +%[move5:] +%a,n + S + IB1 R,A1 + +%[move6:] +%n*,aw +%nb*,a + F* + IBE A2,#1(R) + +%[move7:] +%n*,ew* +%nb*,e* + F* + S1* + IBE #2(R1),#1(R) + +%[move8:] +%n*,e + F* + S1 + IB1 R1,#1(R) + +%[move9:] +%e*,nw* +%eb*,n* + S* + F1* + IBE #2(R),#1(R1) + +%[move10:] +%e*,n + S + F1* + IB1 R,#1(R1) + +%[move11:] +%n*,nw* +%nb*,n* + FS* + S* + IBE #2(R),*(sp)+ + +%[move12:] +%n*,n + FS* + S + IB1 R,*(sp)+ + +%al,z + clr A1 + clr A1+ + +%al,aw + mov A2,A1+ + sxt A1 + +%al,nw* + mov #2(R),A1+ + sxt A1 + +%al,n + S + mov R,A1+ + sxt A1 + +%al,nf + S + setl + movfi R,A1 + seti + +%el*,nf + S + F1* + setl + movfi R,#1(R1) + seti + +%[move13a:] +%al,c + I A2,A1+ + V A1 + +%[move13:] +%al,al + I A2,A1 + I A2+,A1+ + V A1 + +%[move14:] +%al,nl* + S* + I #2(R),A1 + I #2+2(R),A1+ + V A1 + +%[move14a:] +%nl*,c + F* + I A2,2+#1(R) + V #1(R) + +%[move15:] +%al,nl + S + I R,A1 + I R+,A1+ + V A1 + +%nl*,aw + F* + mov A2,#1+2(R) + sxt #1(R) + +%[move16:] +%el*,nl + S + F1* + I R+,#1+2(R1) + V #1(R1) + I R,#1(R1) + +%nl*,n + SS + F* + mov (sp)+,#1+2(R) + sxt #1(R) + +%[move17:] +%nl*,nl + SS + F* + I (sp)+,#1(R) + I (sp)+,#1+2(R) + V #1(R) + +/ =| and =& ~ +ci78: +%a,a +% [move3] + +%a,n +% [move5] + +%n*,a +% [move6] + +%n*,e* +% [move7] + +%n*,e +% [move8] + +%e*,n* +% [move9] + +%e*,n +% [move10] + +%n*,n* +% [move11] + +%n*,n +% [move12] + +%al,c +% [move13a] + +%al,al +% [move13] + +%al,nl* +% [move14] + +%al,nl +% [move15] + +%nl*,c +% [move14a] + +%el*,nl +% [move16] + +%nl*,nl +% [move17] + +/ =+ +ci70: +%n*,z +%a,z + +%a,1 + I'B1 A1 + +%aw,aw +% [move3] + +%aw,nw* +% [move4] + +%aw,n +% [move5] + +%n*,1 +% [move2] + +%ew*,nw* +% [move9] + +%a,nw* + S* + movB1 A1',R1 + I #2(R),R1 + movB1 R1,A1 + +%a,n + S + movB1 A1',R1 + I R,R1 + movB1 R1,A1 + +%ew*,n +% [move10] + +%nw*,n +% [move12] + +%n*,n + SS + F* + movB1 #1(R),R1 + I (sp)+,R1 + movB1 R1,#1(R) + +%al,c +% [move13a] + +%al,al +% [move13] + +%al,nl* +% [move14] + +%al,nl +% [move15] + +%nl*,c +% [move14a] + +%el*,nl +% [move16] + +%nl*,nl +% [move17] + +/ =>> (all harder cases handled by =<< -) +ci75: +%a,1 + asrB1 A1 + +%n*,1 + F* + asrB1 #1(R) + +/ =<< +ci76: +%a,1 + aslB1 A1 + +%n*,1 + F* + aslB1 #1(R) + +%r,aw + ash A2,A1 + +%r,nw* + S* + ash #2(R),A1 + +%r,n + S + ash R,A1 + +/ =<< for longs +ci92: +%al,aw + F + ashc A2,R + mov R,A1 + mov R+,A1+ + +%al,n + SS + F + ashc (sp)+,R + mov R,A1 + mov R+,A1+ + +%nl*,n + FS* + SS + mov 2(sp),R + mov 2(R),R+ + mov (R),R + ashc (sp)+,R + mov R,*(sp) + mov (sp)+,R + mov R+,2(R) + +/ +/ c code tables-- set condition codes +/ + +.globl _cctab + +.data +_cctab=. + 106.; cc60 + 28.; rest + 55.; rest + 34.; rest + 35.; rest + 36.; rest + 37.; rest + 40.; rest + 41.; rest + 42.; rest + 43.; rest + 45.; rest + 46.; rest + 81.; cc81 / & as in "if ((a&b)==0)" + 48.; rest + 60.; cc60 + 61.; cc60 + 62.; cc60 + 63.; cc60 + 64.; cc60 + 65.; cc60 + 66.; cc60 + 67.; cc60 + 68.; cc60 + 69.; cc60 + 72.; rest + 73.; rest + 79.; rest + 0 +.text + +/ relationals +cc60: +%a,z +%ad,zf +% [move1] + +%af,z + movof A1,R + +%n*,z +%nd*,zf +% [move2] + +%nf*,z + F* + movof #1(R),R + +%n,z +%nf,zf + FC + +%aw,aw +%ab,ab +% [move3] + +%nw*,aw +%nb*,ab +% [move6] + +%n,aw +%nf,ad +% [add1] + +%nw*,ew* +%nb*,eb* +% [move7] + +%nw*,e +% [move8] + +%n,ew* +%nf,ed* +% [add2] + +%n,e +%nf,ef +% [add3] + +%nw*,nw* +%nb*,nb* +% [move11] + +%nw*,n +% [move12] + +%n,n +%nf,nf +% [add5] + +/ & as in "if ((a&b) ==0)" +cc81: +%a,a +% [move3] + +%n*,a +% [move6] + +%n,a +% [add1] + +%n,e +% [add3] + +%n,n +% [add5] + +/ set codes right +rest: +%n,n +%nf,nf + H + +/ +/ c code tables-- expression to -(sp) +/ + +.globl _sptab + +.data +_sptab=. + 106.; cs106 + 40.; cs40 + 41.; cs40 + 55.; cs40 + 48.; cs40 + 58.; cs58 + 56.; cs56 + 0 +.text + + +/ name +cs106: +%z,n +%zf,n + clrB1 -(sp) + +%aw,n + mov A1,-(sp) + +%nw*,n + F* + mov #1(R),-(sp) + +%al,n + mov A1+,-(sp) + mov A1,-(sp) + +/ +, -, |, &~ +cs40: +%n,1 + FS + I' (sp) + +%n,aw + FS + I A2,(sp) + +%n,nw* + FS + S* + I #2(R),(sp) + +%n,n + FS + S + I R,(sp) + +/ integer to long +cs58: +%n,n + FS + sxt -(sp) + +/ float to long +cs56: +%nf,n + F + setl + movfi R,-(sp) + seti + -- 2.20.1