+#
+/*
+ * C object code improver-- second part
+ * Copyright 1974 Bell Telephone Laboratories, Incorporated
+ */
+
+#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:
+ 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:
+ 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->op<MOV)
+ return(0);
+ cp1 = p1->code;
+ 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, "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; i<flt+NREG; i++) {
+ if (regs[i][0] != '$')
+ regs[i][0] = 0;
+ conloc[0] = 0;
+ }
+ return;
+ }
+ }
+}
+
+singop(ap)
+struct node *ap;
+{
+ register char *p1, *p2;
+
+ p1 = ap->code;
+ 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<NREG+flt; i++) {
+ if (equstr(regs[i], as))
+ return(i);
+ }
+ return(-1);
+}
+
+isreg(as)
+char *as;
+{
+ register char *s;
+
+ s = as;
+ if (s[0]=='r' && s[1]>='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);
+}