📄 c21.c
字号:
/* If the bit offset is not immediate mode (i.e. $16) * then we can't convert it. */ if (regs[RT1][0] != '$') goto std; /* Get the value of the bit offset and if it is < 0 * then we can't change it. */ if ((boff = getnum(®s[RT1][1])) < 0) goto std; /* If the bit offset is not on an addressable unit * boundary, then we can't change it */ if ((boff % BITS_PER_UNIT) != 0) goto std; /*0001*/ /* Calculate the chunk (addressable unit offset) */ coff = boff / BITS_PER_UNIT ; /*0001*/ /* If the chunk is not zero and the extract is from * a register, then we can't change it since the * CVT or MOVZ can only act on the low byte or word * of the register. The function isreg returns the * register number or -1 if the argument is not a * register. */ if (coff && (isreg(regs[RT3]) >= 0)) goto std; /* Determine whether to do a signed (CVT) or unsigned * MOVZ operation and if the source is a byte or a * word. */ p->op = (p->op == EXTV) ? CVT : MOVZ; p->subop = U((flen == 8 ? BYTE : WORD), LONG); /* Set up the source operand string in regs[RT1] */ if (coff == 0) /* If the addressable offset is 0 then just * copy the source from RT3. */ strcpy(regs[RT1], regs[RT3]); else /* Change the source operand string to use the * chunk. If the source uses general register * addressing generate "coff(Rn)" otherwise * generate "coff+address". */ sprintf(regs[RT1], "%d%s%s", coff, regs[RT3][0]=='(' ? "":"+", regs[RT3]); /* Move the destination from RT4 to RT2 and set the * RT3 and RT4 to null strings since we no longer need * them to generate the instruction. */ 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: case INC: case DEC: splitrand(p); dest(lastrand,p->subop); if (p->op==CLR) if ((r = isreg(regs[RT1])) >= 0) savereg(r, "$0", p->subop); else setcon("$0", regs[RT1], p->subop); break;/* .rx */ case TST: case PUSH: splitrand(p); lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */ repladdr(p); if (p->op==TST && equstr(lastrand=regs[RT1], ccloc+1) && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop)) &&!source(lastrand)) { delnode(p); p = p->back; nrtst++; nchange++; } setcc(lastrand,p->subop); break;/* .rx,.rx,.rx */ case PROBER: case PROBEW: case CASE: case MOVC3:/* .rx,.rx */ case MTPR: case CALLS: case CMP: case BIT: splitrand(p); /* fool repladdr into doing right number of operands */ if (p->op==CASE || p->op==PROBER || p->op==PROBEW) lastrand=regs[RT4];/* else if (p->op==CMPV || p->op==CMPZV) lastrand=regs[RT4+1]; */ else if (p->op==MOVC3) lastrand=regs[RT1]; else lastrand=regs[RT3]; repladdr(p); if (p->op==CALLS || p->op==MOVC3) clearreg(); if (p->op==BIT) bitopt(p); ccloc[0]=0; break; case CBR: if (p->subop>=JBC) { splitrand(p); if (p->subop<JBCC) lastrand=regs[RT3]; /* 2 operands can be optimized */ else lastrand=regs[RT2]; /* .mb destinations lose */ repladdr(p); } ccloc[0] = 0; break; case JBR: redunbr(p);/* .wx,.bb */ case SOB: default: clearreg(); } }}char *byondrd(p) /* Return pointer to register which is "beyond last read/modify operand" */ register struct node *p;{ if (OP2==(p->subop>>4)) return(regs[RT3]); switch (p->op) { /* 1 operand instructions */ case JSB: case TST: case INC: case DEC: case PUSHA: case PUSH: return(regs[RT2]); /* 2 operand instructions */ case MFPR: /* DLB0004 */ case MTPR: case BIT: case CMP: case CALLS: return(regs[RT3]); /* 3 operand instructions */ case PROBER: case PROBEW: case CASE: case MOVC3: return(regs[RT4]); } return(lastrand);}struct node *bflow(p)register struct node *p;{ register char *cp1,*cp2,**preg; register int r; int flow= -1; struct node *olduse=0; splitrand(p); if (p->op!=PUSH && p->subop && 0<=(r=isreg(lastrand)) && r<NUSE && uses[r]==p->forw) { if (equtype(p->subop,regs[r][0]) || ((p->op==CVT || p->op==MOVZ) && 0xf®s[r][0] && compat(0xf&(p->subop>>4),regs[r][0]))) { register int r2; if (regs[r][1]!=0) {/* send directly to destination */ if (p->op==INC || p->op==DEC) { if (p->op==DEC) p->op=SUB; else p->op=ADD; p->subop=(OP2<<4)+(p->subop&0xF); /* use 2 now, convert to 3 later */ p->pop=0; cp1=lastrand; cp2=regs[RT2]; while (*cp2++= *cp1++); /* copy reg */ cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; } cp1=regs[r]+1; cp2=lastrand; if (OP2==(p->subop>>4)) {/* use 3 operand form of instruction */ p->pop=0; p->subop += (OP3-OP2)<<4; lastrand=cp2=regs[RT3]; } while (*cp2++= *cp1++); if (p->op==MOVA && p->forw->op==PUSH) { p->op=PUSHA; *regs[RT2]=0; p->pop=0; } else if (p->op==MOV && p->forw->op==PUSH) { p->op=PUSH ; *regs[RT2]=0; p->pop=0; } delnode(p->forw); if (0<=(r2=isreg(lastrand)) && r2<NUSE) { uses[r2]=uses[r]; uses[r]=0; } redun3(p,0); newcode(p); redunm++; flow=r; } else if (p->op==MOV && p->forw->op!=EXTV && p->forw->op!=EXTZV) { /* superfluous fetch */ int nmatch; char src[C2_ASIZE]; movit: cp2=src; cp1=regs[RT1]; while (*cp2++= *cp1++); splitrand(p->forw); if (p->forw->op != INC && p->forw->op != DEC) lastrand=byondrd(p->forw); nmatch=0; for (preg=regs+RT1;*preg!=lastrand;preg++) if (r==isreg(*preg)) { cp2= *preg; cp1=src; while (*cp2++= *cp1++); ++nmatch; } if (nmatch==1) { if (OP2==(p->forw->subop>>4) && equstr(src,regs[RT2])) { p->forw->pop=0; p->forw->subop += (OP3-OP2)<<4; cp1=regs[RT3]; *cp1++='r'; *cp1++=r+'0'; *cp1=0; } delnode(p); p=p->forw; if (0<=(r2=isreg(src)) && r2<NUSE) { uses[r2]=uses[r]; uses[r]=0; } redun3(p,0); newcode(p); redunm++; flow=r; } else splitrand(p); } } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && p->forw->subop&0xf /* if base or index, then forget it */ && compat(p->subop,p->forw->subop) && !source(cp1=regs[RT1]) && !indexa(cp1)) goto movit; } /* adjust 'lastrand' past any 'read' or 'modify' operands. */ lastrand=byondrd(p); /* a 'write' clobbers the register. */ if (0<=(r=isreg(lastrand)) && r<NUSE || OP2==(p->subop>>4) && 0<=(r=isreg(regs[RT2])) && r<NUSE && uses[r]==0) { /* writing a dead register is useless, but watch side effects */ switch (p->op) { case ACB: case AOBLEQ: case AOBLSS: case SOBGTR: case SOBGEQ: break; default: if (uses[r]==0) {/* no direct uses, check for use of condition codes */ register struct node *q=p; while ((q=nonlab(q->forw))->combop==JBR) q=q->ref; /* cc unused, unchanged */ if (q->op!=CBR) {/* ... and destroyed */ preg=regs+RT1; while (cp1= *preg++) { if (cp1==lastrand) {redunm++; delnode(p); return(p->forw);} if (source(cp1) || equstr(cp1,lastrand)) break; } } } flow=r; } } if (0<=(r=flow)) {olduse=uses[r]; uses[r]=0; *(short *)(regs[r])=0;} /* these two are here, rather than in bmove(), /* because I decided that it was better to go for 3-address code /* (save time) rather than fancy jbxx (save 1 byte) /* on sequences like bisl2 $64,r0; movl r0,foo */ if (p->op==BIC) {p=bicopt(p); splitrand(p); lastrand=byondrd(p);} if (p->op==BIS) {bixprep(p,JBSS); lastrand=byondrd(p);} /* now look for 'read' or 'modify' (read & write) uses */ preg=regs+RT1; while (*(cp1= *preg++)) { /* check for r */ if (lastrand!=cp1 && 0<=(r=isreg(cp1)) && r<NUSE && uses[r]==0) { uses[r]=p; cp2=regs[r]; *cp2++=p->subop; if (p->op==ASH && preg==(regs+RT1+1)) cp2[-1]=BYTE; /* stupid DEC */ if (p->op==MOV || p->op==PUSH || p->op==CVT || p->op==MOVZ || p->op==COM || p->op==NEG) { if (p->op==PUSH) cp1="-(sp)"; else { cp1=regs[RT2]; if (0<=(r=isreg(cp1)) && r<NUSE && uses[r]==0) uses[r]=olduse; /* reincarnation!! */ /* as in addl2 r0,r1; movl r1,r0; ret */ if (p->op!=MOV) cp1=0; } if (cp1) while (*cp2++= *cp1++); else *cp2=0; } else *cp2=0; continue; } /* check for (r),(r)+,-(r),[r] */ do if (*cp1=='(' || *cp1=='[') {/* get register number */ char t; cp2= ++cp1; while (*++cp1!=')' && *cp1!=']'); t= *cp1; *cp1=0; if (0<=(r=isreg(cp2)) && r<NUSE && (uses[r]==0 || uses[r]==p)) { uses[r]=p; regs[r][0]=(*--cp2=='[' ? OPX<<4 : OPB<<4); } *cp1=t; } while (*++cp1); } /* pushax or movax possibility? */ cp1=regs[RT1]; if (*cp1++=='$' && isstatic(cp1) && natural(regs[RT1])) { if (p->combop==T(MOV,LONG)) { if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { cp1=p->code; while (*cp1++!=','); p->code= --cp1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -