📄 c21.c
字号:
register char *s;{ register int i; (void) source(s); /* handle addressing side effects */ if (!natural(s)) { /* wild store, everything except constants vanishes */ for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0; conloc[0] = 0; ccloc[0] = 0; return; } if ((i = isreg(s)) >= 0) { /* if register destination, that reg is a goner */ *(short *)(regs[i]) = 0; switch(type & 0xF){ case DFLOAT: /* clobber two at once */ /*FALLTHROUGH*/ case GFLOAT: *(short *)(regs[i+1]) = 0; break; case HFLOAT: /* clobber four at once */ *(short *)(regs[i+1]) = 0; *(short *)(regs[i+2]) = 0; *(short *)(regs[i+3]) = 0; break; } switch((type>>4)&0xF){ case DFLOAT: /* clobber two at once */ /*FALLTHROUGH*/ case GFLOAT: *(short *)(regs[i+1]) = 0; break; case HFLOAT: /* clobber four at once */ *(short *)(regs[i+1]) = 0; *(short *)(regs[i+2]) = 0; *(short *)(regs[i+3]) = 0; break; } } for (i=NREG; --i>=0;) if (regs[i][1]=='*' && equstr(s, regs[i]+2)) *(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */ while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */ *(short *)(regs[i]) = 0; if (*conloc && equstr(conloc, s)) conloc[0] = 0; setcc(s, type); /* natural destinations set condition codes */}splitrand(p) struct node *p; {/* separate operands at commas, set up 'regs' and 'lastrand' */register char *p1, *p2; register char **preg;preg=regs+RT1;if (p1=p->code) while (*p1) { lastrand=p2= *preg++; while (*p1) if (','==(*p2++= *p1++)) {--p2; break;} *p2=0;}while (preg<(regs+RT1+5)) *(*preg++)=0;}compat(have, want)/* See if the the operand types are compatible. "have" contains the source * and destination types for an instruction (which we may be trying to * replace). "want" contains the operand type we want as a result. DLB003 */{ register int wanted_type, /* Type we want to end with */ src_type, /* Source type of instruction */ dst_type; /* Destination type of " */ /* Get "wanted_type" from "want" and if it is 0 then we have * wildcard request so anything matches. */ if ( (wanted_type = (want & 0xF)) == 0) return(1); /* Extract the source and destination tyes from "have". If the * destination type is wildcard or one of the OPx types then make * it the same as the source. DLB003 */ src_type=have&0xF; dst_type=((have>>4)&0xF); if (dst_type==0 || (dst_type>=OP2 && dst_type<=OPX)) dst_type=src_type; /* If the wanted_type is not BYTE, WORD, or LONG, then the * types are compatible only if all three are the same. DLB003 */ if (wanted_type>=FFLOAT) return(dst_type==wanted_type && src_type==wanted_type); /* Otherwise, the types are compatible only if the the destination * type is a BYTE, WORD, or LONG and both the destination and * sources types are larger than the wanted type. DLB003 */ return(dst_type<FFLOAT && dst_type>=wanted_type && src_type>=wanted_type );}equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}findrand(as, type)char *as;{ register char **i; for (i = regs+NREG; --i>=regs;) { if (**i && equstr(*i+1, as) && compat(**i,type)) return(i-regs); } return(-1);}isreg(s)register char *s;{ if (*s++!='r' || !isdigit(*s++)) return(-1); if (*s==0) return(*--s-'0'); if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'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(-1); lp = p; }}source(ap)char *ap;{ register char *p1, *p2; p1 = ap; p2 = p1; if (*p1==0) return(0); while (*p2++ && *(p2-1)!='['); if (*p1=='-' && *(p1+1)=='(' || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='(' || *(p2-2)=='+') { while (*p1 && *p1++!='r'); if (isdigit(*p1++)) if (isdigit(*p1)) *(short *)(regs[10+*p1-'0'])=0; else *(short *)(regs[*--p1-'0'])=0; return(1); } return(0);}newcode(p) struct node *p; { register char *p1,*p2,**preg; preg=regs+RT1; p2=line; while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';} *--p2=0; p->code=copy(line);}repladdr(p)struct node *p;{ register r; register char *p1, *p2; char **preg; int nrepl; preg=regs+RT1; nrepl=0; while (lastrand!=(p1= *preg++)) if (!source(p1) && 0<=(r=findrand(p1,p->subop))) { *p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0; nrepl++; nsaddr++; } if (nrepl) newcode(p);}/* 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(p)register struct node *p;{ register struct node *p1; register char *ap1; char *ap2; if ((p1 = p->ref) == 0) return; p1 = nonlab(p1); if (p1->op==TST) { splitrand(p1); savereg(RT2, "$0", p1->subop); } else if (p1->op==CMP) splitrand(p1); else return; if (p1->forw->op==CBR) { ap1 = findcon(RT1, p1->subop); ap2 = findcon(RT2, p1->subop); p1 = p1->forw; if (compare(p1->subop, ap1, ap2)) { nredunj++; nchange++; decref(p->ref); p->ref = p1->ref; p->labno = p1->labno;#ifdef COPYCODE if (p->labno == 0) p->code = p1->code; if (p->ref)#endif p->ref->refc++; } } else if ( p1->op==TST && equstr(regs[RT1],ccloc+1) && equtype(ccloc[0],p1->subop) ) { /* The results of the TST aren't used, so we can just * branch past it. Insert a new label in front of the * TST, dereference the old label, and set up the branch * to go to the new label. */ p1=insertl(p1->forw); decref(p->ref); p->ref = p1; p->labno = p1->labno; nrtst++; nchange++; }}char *findcon(i, type){ register char *p; register r; p = regs[i]; if (*p=='$') return(p); if ((r = isreg(p)) >= 0 && compat(regs[r][0],type)) return(regs[r]+1); if (equstr(p, conloc)) return(conval+1); return(p);}compare(op, acp1, acp2)char *acp1, *acp2;{ register char *cp1, *cp2; register n1; int n2; int sign; cp1 = acp1; cp2 = acp2; if (*cp1++ != '$' || *cp2++ != '$') return(0); n1 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;} while (isdigit(*cp2)) {n1 *= 10; n1 += (*cp2++ - '0')*sign;} n2 = n1; n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;} while (isdigit(*cp1)) {n1 *= 10; n1 += (*cp1++ - '0')*sign;} 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(((int)cp1) <= ((int)cp2)); case JGE: return(((int)cp1) >= ((int)cp2)); case JLT: return(((int)cp1) < ((int)cp2)); case JGT: return(((int)cp1) > ((int)cp2)); case JLO: return(cp1 < cp2); case JHI: return(cp1 > cp2); case JLOS: return(cp1 <= cp2); case JHIS: return(cp1 >= cp2); } return(0);}setcon(cv, cl, type)register char *cv, *cl;{ register char *p; if (*cv != '$') return; if (!natural(cl)) return; p = conloc; while (*p++ = *cl++); p = conval; *p++ = type; while (*p++ = *cv++);}equstr(p1, p2)register char *p1, *p2;{ do { if (*p1++ != *p2) return(0); } while (*p2++); return(1);}setcc(ap,type)char *ap;{ register char *p, *p1; p = ap; if (!natural(p)) { ccloc[0] = 0; return; } p1 = ccloc; *p1++ = type; while (*p1++ = *p++);}okio(p) register char *p; {/* 0->probable I/O space address; 1->not */ if (ioflag && (!natural(p) || 0>getnum(p))) return(0); return(1);}indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */ while (*p) if (*p++=='[') return(1); return(0);}autoid(p) register char *p ; /* operand address string *//* See if operand addressing mode uses auto(in|de)crement. * Return 1 for yes, 0 for no. */{ if (*p == '-' && *(p+1) == '(') return(1) ; /* autodecrement */ while (*p) p++; /* find end of string */ if (*--p == '+' && *--p == ')') return(1) ; /* autoincrement */ return(0) ; /* neither */}natural(p)register char *p;{/* 1->simple local, parameter, global, or register; 0->otherwise */ if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(' || *p=='$'&&getnum(p+1)) return(0); while (*p++); p--; if (*--p=='+' || *p==']' || *p==')' && *(p-2)!='a' && *(p-2)!='f') return(0); return(1);}/*** Tell if an argument is most likely static.*/isstatic(cp)register char *cp;{ if (*cp == '_' || *cp == 'L' || (*cp++ == 'v' && *cp == '.')) return (1); return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -