📄 c10.c
字号:
goto subtre; /* H */ case 'H': p = tree; flag = 04; subtre: ctable = regtab; if (flag&04) ctable = cregtab; 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||tree->op==ITOL)) 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) movreg(rreg, reg1, p); else reg1 = rreg; } else if (rreg!=reg) if ((c&020)==0 && oddreg(tree, 0)==0 && tree->type!=LONG && (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 movreg(rreg, reg, p); 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 || r>=4 && tree->type==DOUBLE) 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; /* * Certain adjustments for / % and PTOI */ case 'T': c = reg-1; if (tree->op == PTOI) { printf("bic r%d,r%d\nsbc r%d\n", c,c,c); goto loop; } if (p1->type==UNSIGN || p1->type&XTYPE) { printf("clr r%d\n", c); goto loop; } if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0)) printf("tst r%d\n", reg); printf("sxt r%d\n", c); goto loop; case 'V': /* adc sbc, clr, or sxt 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; case ASSIGN: p = tree->tr2; goto lcasev; case ASDIV: case ASMOD: case ASULSH: p = tree->tr1; lcasev: if (p->type!=LONG) { if (p->type==UNSIGN || p->type&XTYPE) printf("clr"); else printf("sxt"); goto loop; } default: while ((c = *string++)!='\n' && c!='\0'); break; } goto loop; /* * Mask used in field assignments */ case 'Z': printf("$%o", tree->mask); goto loop; /* * Relational on long values. * Might bug out early. E.g., * (long<0) can be determined with only 1 test. */ case 'X': if (xlongrel(*string++ - '0')) return(reg); 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, o; register struct tnode *p; p = *treep; o = p->op; if (opdope[o]&LEAF || o==LOGOR || o==LOGAND) return(0); while(sreorder(&p->tr1, regtab, reg, 1)) ; if (opdope[o]&BINARY) while(sreorder(&p->tr2, regtab, reg, 1)) ; r = 0; if (table!=cctab) while (sreorder(treep, table, reg, 0)) 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, recurf)struct tnode **treep;struct table *table;{ register struct tnode *p, *p1; p = *treep; if (opdope[p->op]&LEAF) return(0); if (p->op==PLUS && recurf) if (reorder(&p->tr2, table, reg)) *treep = p = optim(p); p1 = p->tr1; if (p->op==STAR || p->op==PLUS) { if (recurf && 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||p1->type==CHAR||isfloat(p->tr2)) return(0); if (p->op==ASSIGN) switch (p->tr2->op) { case TIMES: if (!ispow2(p->tr2)) break; p->tr2 = pow2(p->tr2); case PLUS: case MINUS: case AND: case ANDN: case OR: case EXOR: case LSHIFT: case RSHIFT: p1 = p->tr2->tr2; if (xdcalc(p1, 16) > 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: if (!ispow2(p)) return(0); case ASPLUS: case ASMINUS: case ASAND: case ASANDN: case ASOR: case ASXOR: case INCBEF: case DECBEF: 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 ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) { return(1+rcexpr(p->tr1, table, reg)); } p1 = 0; if (opdope[p->op]&BINARY) { if (p->op==LOGAND || p->op==LOGOR) return(0); } 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, *q; p = ap; if (p->class!=REG) return(p); q = getblk(sizeof(*p)); q->op = p->op; q->type = p->type; q->class = p->class; q->offset = p->offset; q->nloc = p->nloc; return(q);}/* * 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; int i; int size; tree = atree; if (tree->op==STRASG) { size = tree->mask; tree = tree->tr1; tree = strfunc(tree); if (size <= 2) { setype(tree, INT); goto normal; } if (size <= 4) { setype(tree, LONG); goto normal; } if (tree->op!=NAME && tree->op!=STAR) { error("Unimplemented structure assignment"); return(0); } tree = tnode(AMPER, STRUCT+PTR, tree); tree = tnode(PLUS, STRUCT+PTR, tree, tconst(size, INT)); tree = optim(tree); retval = rcexpr(tree, regtab, 0); size =>> 1; if (size <= 5) { for (i=0; i<size; i++) printf("mov -(r%d),-(sp)\n", retval); } else { if (retval!=0) printf("mov r%d,r0\n", retval); printf("mov $%o,r1\n", size); printf("L%d:mov -(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn, isn); isn++; } nstack++; return(size*2); }normal: 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);}struct tnode *strfunc(atp)struct tnode *atp;{ register struct tnode *tp; tp = atp; if (tp->op != CALL) return(tp); setype(tp, STRUCT+PTR); return(tnode(STAR, STRUCT, tp));}/* * Compile an initializing expression */doinit(atype, atree)struct tnode *atree;{ register struct tnode *tree; register int type; float sfval; double fval; long lval; tree = atree; type = atype; if (type==CHAR) { printf(".byte "); if (tree->type&XTYPE) goto illinit; type = INT; } if (type&XTYPE) type = INT; switch (type) { case INT: case UNSIGN: if (tree->op==FTOI) { if (tree->tr1->op!=FCON && tree->tr1->op!=SFCON) goto illinit; tree = tree->tr1; tree->value = tree->fvalue; tree->op = CON; } else if (tree->op==LTOI) { if (tree->tr1->op!=LCON) goto illinit; tree = tree->tr1; lval = tree->lvalue; tree->op = CON; tree->value = lval; } if (tree->op == CON) printf("%o\n", tree->value); else if (tree->op==AMPER) { pname(tree->tr1, 0); putchar('\n'); } else goto illinit; return; case DOUBLE: case FLOAT: if (tree->op==ITOF) { if (tree->tr1->op==CON) { fval = tree->tr1->value; } else goto illinit; } else if (tree->op==FCON || tree->op==SFCON) fval = tree->fvalue; else if (tree->op==LTOF) { if (tree->tr1->op!=LCON) goto illinit; fval = tree->tr1->lvalue; } else goto illinit; if (type==FLOAT) { sfval = fval; printf("%o; %o\n", sfval); } else printf("%o; %o; %o; %o\n", fval); return; case LONG: if (tree->op==FTOL) { tree = tree->tr1; if (tree->op==SFCON) tree->op = FCON; if (tree->op!= FCON) goto illinit; lval = tree->fvalue; } else if (tree->op==ITOL) { if (tree->tr1->op != CON) goto illinit; lval = tree->tr1->value; } else if (tree->op==LCON) lval = tree->lvalue; else goto illinit; printf("%o; %o\n", lval); return; }illinit: error("Illegal initialization");}movreg(r0, r1, tree)struct tnode *tree;{ register char *s; if (r0==r1) return; if (tree->type==LONG) { s = "mov r%d,r%d\nmov r%d,r%d\n"; if (r0 < r1) printf(s, r0+1,r1+1,r0,r1); else printf(s, r0,r1,r0+1,r1+1); return; } printf("mov%c r%d,r%d\n", isfloat(tree), r0, r1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -