📄 c21.c
字号:
static char sccsid[] = "@(#)c21.c 4.7 7/8/81";/* char C21[] = {"@(#)c21.c 1.83 80/10/16 21:18:22 JFR"}; /* sccs ident *//* * C object code improver-- second part */#include "c2.h"#include <stdio.h>#include <ctype.h>#define NUSE 6int ioflag;int biti[NUSE] = {1,2,4,8,16,32};int bitsize[4] = {0,8,16,32}; /* index by type codes */int pos,siz; long f; /* for bit field communication */struct node *uses[NUSE]; /* for backwards flow analysis */char *lastrand; /* last operand of instruction */struct node *bflow();struct node *bicopt();char *findcon();redun3(p,split) register struct node *p; int split; {/* check for 3 addr instr which should be 2 addr */ if (OP3==((p->subop>>4)&0xF)) { if (split) splitrand(p); if (equstr(regs[RT1],regs[RT3]) && (p->op==ADD || p->op==MUL || p->op==BIS || p->op==XOR)) { register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t; } if (equstr(regs[RT2],regs[RT3])) { p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0; lastrand=regs[RT2]; *regs[RT3]=0; return(1); } } return(0);}bmove() { register struct node *p, *lastp; register char *cp1,*cp2; register int r; refcount(); for (p=lastp= &first; 0!=(p=p->forw); lastp=p); clearreg(); clearuse(); for (p=lastp; p!= &first; p=p->back) { if (debug) { printf("Uses:\n"); for (r=NUSE;--r>=0;) if (uses[r]) printf("%d: %s\n",r,uses[r]->code? uses[r]->code:""); printf("-\n"); } r=(p->subop>>4)&0xF; if (OP2==r && (cp1=p->code, *cp1++)=='$' && *cp1++=='0' && *cp1++==',' && !source(cp1)) {/* a no-op unless MUL or DIV */ if (p->op==MUL) {p->op=MOV; p->subop&=0xF; p->pop=0;} else if (p->op==DIV) fprintf(stderr,"c2: zero divide\n"); else {delnode(p); redunm++; continue;} } if (OP3==r && 0!=redun3(p,1)) {newcode(p); redunm++;} switch (p->op) { case LABEL: case DLABEL: for (r=NUSE; --r>=0;) if (uses[r]) p->ref=(struct node *) (((int)p->ref)|biti[r]); break; case CALLS: clearuse(); goto std; case 0: clearuse(); break; case SUB: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; if (*cp1++!='$') goto std; splitrand(p); if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ char buf[C2_ASIZE]; cp2=buf; *cp2++='-'; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; cp1="(fp),"; while (*cp2++= *cp1++); --cp2; cp1=regs[RT3]; while (*cp2++= *cp1++); p->code=copy(buf); p->combop=T(MOVA,LONG); p->pop=0; } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) { p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1; } goto std; case ADD: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; if (*cp1++!='$') goto std; splitrand(p); if (isstatic(cp1) && (r=isreg(regs[RT2]))>=0 && r<NUSE && uses[r]==p->forw) { /* address comp: ** addl2 $_foo,r0 \ movab _foo[r0],bar ** movl r0,bar / */ register struct node *pnext = p->forw; char buf[C2_ASIZE]; if (pnext->op == MOV && pnext->subop == LONG) { cp1 = ®s[RT1][1]; cp2 = &buf[0]; while (*cp2++ = *cp1++) ; cp2--; splitrand(pnext); if (r == isreg(regs[RT1])) { delnode(p); p = pnext; p->op = MOVA; p->subop = BYTE; p->pop = 0; cp1 = regs[RT1]; *cp2++ = '['; while (*cp2++ = *cp1++) ; cp2--; *cp2++ = ']'; *cp2++ = ','; cp1 = regs[RT2]; while (*cp2++ = *cp1++) ; p->code = copy(buf); } } } else if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=','; p->combop=T(MOVA,LONG); p->pop=0; } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) { p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1; } /* fall thru ... */ case CASE: default: std: p=bflow(p); break; case MUL: { /* ** Change multiplication by constant powers of 2 to ** shifts. */ splitrand(p); if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std; if ((r = ispow2(getnum(®s[RT1][1]))) < 0) goto std; switch (r) { case 0: /* mull3 $1,x,y */ if (p->subop == U(LONG,OP3)) { if (equstr(regs[RT2], regs[RT3])) { delnode(p); p = p->forw; } else { p->op = MOV; p->subop = LONG; p->pop = 0; newcode(p); nchange++; } } else if (p->subop == U(LONG,OP2)) { delnode(p); p = p->forw; } goto std; case 1: /* mull2 $2,x */ if (p->subop == U(LONG, OP2) && !source(regs[RT2])) { strcpy(regs[RT1], regs[RT2]); p->op = ADD; p->pop = 0; newcode(p); nchange++; } goto std; } if(p->subop==U(LONG,OP3)||(p->subop==U(LONG,OP2)&&!source(regs[RT2]))) { if (p->subop == U(LONG,OP2)) strcpy(regs[RT3], regs[RT2]); sprintf(regs[RT1], "$%d", r); p->op = ASH; p->subop = LONG; p->pop = 0; newcode(p); nchange++; } goto std; } case ASH: { /* address comp: ** ashl $1,bar,r0 \ movl bar,r0 ** movab _foo[r0] / movaw _foo[r0] ** ** ashl $2,r0,r0 \ moval _foo[r0] ** movab _foo[r0] / */ register struct node *pf; register int shfrom, shto; long shcnt; char *regfrom; splitrand(p); if (regs[RT1][0] != '$') goto std; if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 3) goto std; if ((shfrom = isreg(regs[RT2])) >= 0) regfrom = copy(regs[RT2],"]"); if ((shto = isreg(regs[RT3])) >= 0 && shto<NUSE) { int regnum; if (uses[shto] != (pf = p->forw)) goto ashadd; if (pf->op != MOVA && pf->op != PUSHA) goto ashadd; if (pf->subop != BYTE) goto ashadd; splitrand(pf); if (!indexa(regs[RT1])) goto std; cp2 = regs[RT1]; if(!isstatic(cp2)) goto std; while (*cp2++ != '[') ; if (*cp2++ != 'r' || !isdigit(*cp2)) goto std; regnum = *cp2++ - '0'; if (isdigit(*cp2)) { if (cp2[1] != ']') goto std; regnum *= 10; regnum += *cp2 - '0'; } if (regnum != shto) goto std; if (shfrom >= 0) /* ashl $N,r*,r0 */ { delnode(p); if (shfrom != shto) { uses[shto] = NULL; splitrand(pf); cp2=regs[RT1]; while (*cp2++!='['); cp1=regfrom; while (*cp2++= *cp1++); newcode(pf); } } else { p->op = MOV; splitrand(p); strcpy(regs[RT1], regs[RT2]); strcpy(regs[RT2], regs[RT3]); regs[RT3][0] = '\0'; p->pop = 0; newcode(p); } switch (shcnt) { case 1: pf->subop = WORD; break; case 2: pf->subop = LONG; break; case 3: pf->subop = QUAD; break; } redunm++; nsaddr++; nchange++; } goto std;ashadd: /* at this point, RT2 and RT3 are guaranteed to be simple regs*/ if (shcnt == 1 && equstr(regs[RT2], regs[RT3])) { /* ** quickie: ** ashl $1,A,A > addl2 A,A */ p->op = ADD; p->subop = U(LONG,OP2); p->pop = 0; strcpy(regs[RT1], regs[RT2]); regs[RT3][0] = '\0'; newcode(p); nchange++; } goto std; } case EXTV: case EXTZV: { /* bit tests: ** extv A,$1,B,rC \ ** tstl rC > jbc A,B,D ** jeql D / ** ** also byte- and word-size fields: ** extv $n*8,$8,A,B > cvtbl n+A,B ** extv $n*16,$16,A,B > cvtwl n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B ** extzv $n*16,$16,A,B > movzwl n+A,B */ register struct node *pf; /* forward node */ register struct node *pn; /* next node (after pf) */ int flen; /* field length */ splitrand(p); if (regs[RT2][0] != '$') goto std; if ((flen = getnum(®s[RT2][1])) < 0) goto std; if (flen == 1) { register int extreg; /* reg extracted to */ extreg = isreg(regs[RT4]); if (extreg < 0 || extreg >= NUSE) goto std; if ((pf = p->forw)->op != TST) goto std; if (uses[extreg] && uses[extreg] != pf) goto std; splitrand(pf); if (extreg != isreg(regs[RT1])) goto std; if ((pn = pf->forw)->op != CBR) goto std; if (pn->subop != JEQ && pn->subop != JNE) goto std; delnode(p); delnode(pf); pn->subop = (pn->subop == JEQ) ? JBC : JBS; for(cp2=p->code; *cp2++!=',';); for(cp1=cp2; *cp1++!=',';); while (*cp1!=',') *cp2++= *cp1++; *cp2='\0'; pn->code = p->code; pn->pop = NULL; uses[extreg] = NULL; } else if (flen == 8 || flen == 16) { register int boff; /* bit offset */ register int coff; /* chunk (byte or word) offset*/ if (regs[RT1][0] != '$') goto std; if ((boff = getnum(®s[RT1][1])) < 0) goto std; coff = boff / flen; if (coff && (isreg(regs[RT3]) >= 0)) goto std; if (boff < 0 || (boff % flen) != 0) goto std; p->op = (p->op == EXTV) ? CVT : MOVZ; p->subop = U((flen == 8 ? BYTE : WORD), LONG); if (coff == 0) strcpy(regs[RT1], regs[RT3]); else sprintf(regs[RT1], "%d%s%s", coff, regs[RT3][0]=='(' ? "":"+", regs[RT3]); strcpy(regs[RT2], regs[RT4]); regs[RT3][0] = '\0'; regs[RT4][0] = '\0'; p->pop = 0; newcode(p); } nchange++; goto std; } case CMP: { /* comparison to -63 to -1: ** cmpl r0,$-1 > incl r0 ** jeql ... ** ** cmpl r0,$-63 > addl2 $63,r0 ** jeql ... */ register int num; register int reg; register struct node *regp = p->back; if (p->forw->op != CBR) goto std; if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std; splitrand(p); if (strncmp(regs[RT2], "$-", 2) != 0) goto std; reg = r = isreg(regs[RT1]); if (r < 0) goto std; if (r < NUSE && uses[r] != 0) goto std; if (r >= NUSE && regp->op == MOV && p->subop == regp->subop) { if (*regp->code != 'r') goto std; reg = regp->code[1] - '0'; if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg]) goto std; } if (r >= NUSE) goto std; if (reg != r) sprintf(regs[RT1], "r%d", reg); if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std; if (num == 1) { p->op = INC; regs[RT2][0] = '\0'; } else { register char *t; t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t; p->op = ADD; p->subop = U(p->subop, OP2); for (t = ®s[RT1][2]; t[-1] = *t; t++) ; } p->pop = 0; newcode(p); nchange++; goto std; } case JSB: if (equstr(p->code,"mcount")) {uses[0]=p; regs[0][0]= -1;} goto std; case JBR: case JMP: clearuse(); if (p->subop==RET || p->subop==RSB) {uses[0]=p; regs[0][0]= -1; break;} if (p->ref==0) goto std; /* jmp (r0) */ /* fall through */ case CBR: if (p->ref->ref!=0) for (r=NUSE;--r>=0;) if (biti[r] & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;} case EROU: case JSW: case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; } } for (p= &first; p!=0; p=p->forw) if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */}rmove(){ register struct node *p, *lastp; register int r; int r1; clearreg(); for (p=first.forw; p!=0; p = p->forw) { lastp=p; if (debug) { printf("Regs:\n"); for (r=0; r<NREG; r++) if (regs[r][0]) { r1=regs[r][0]; printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1); } printf("-\n"); } switch (p->op) { case CVT: splitrand(p); goto mov; case MOV: splitrand(p); if ((r = findrand(regs[RT1],p->subop)) >= 0) { if (r == isreg(regs[RT2]) && p->forw->op!=CBR) { delnode(p); redunm++; break; } }mov: repladdr(p); r = isreg(regs[RT1]); r1 = isreg(regs[RT2]); dest(regs[RT2],p->subop); if (r>=0) { if (r1>=0) savereg(r1, regs[r]+1, p->subop); else if (p->op!=CVT) savereg(r, regs[RT2], p->subop); } else if (r1>=0) savereg(r1, regs[RT1], p->subop); else if (p->op!=CVT) setcon(regs[RT1], regs[RT2], p->subop); break;/* .rx,.wx */ case MFPR: case COM: case NEG:/* .rx,.wx or .rx,.rx,.wx */ case ADD: case SUB: case BIC: case BIS: case XOR: case MUL: case DIV: case ASH: case MOVZ:/* .rx,.rx,.rx,.wx */ case EXTV: case EXTZV: case INSV: splitrand(p); repladdr(p); dest(lastrand,p->subop); if (p->op==INSV) ccloc[0]=0; break;/* .mx or .wx */ case CLR:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -