diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/vl/noop.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vl/noop.c')
-rwxr-xr-x | sys/src/cmd/vl/noop.c | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/sys/src/cmd/vl/noop.c b/sys/src/cmd/vl/noop.c new file mode 100755 index 000000000..337e947d3 --- /dev/null +++ b/sys/src/cmd/vl/noop.c @@ -0,0 +1,416 @@ +#include "l.h" + +void +noops(void) +{ + Prog *p, *p1, *q, *q1; + int o, curframe, curbecome, maxbecome; + + /* + * find leaf subroutines + * become sizes + * frame sizes + * strip NOPs + * expand RET + * expand BECOME pseudo + */ + + if(debug['v']) + Bprint(&bso, "%5.2f noops\n", cputime()); + Bflush(&bso); + + curframe = 0; + curbecome = 0; + maxbecome = 0; + curtext = 0; + + q = P; + for(p = firstp; p != P; p = p->link) { + + /* find out how much arg space is used in this TEXT */ + if(p->to.type == D_OREG && p->to.reg == REGSP) + if(p->to.offset > curframe) + curframe = p->to.offset; + + switch(p->as) { + case ATEXT: + if(curtext && curtext->from.sym) { + curtext->from.sym->frame = curframe; + curtext->from.sym->become = curbecome; + if(curbecome > maxbecome) + maxbecome = curbecome; + } + curframe = 0; + curbecome = 0; + + p->mark |= LABEL|LEAF|SYNC; + if(p->link) + p->link->mark |= LABEL; + curtext = p; + break; + + /* too hard, just leave alone */ + case AMOVW: + if(p->to.type == D_FCREG || + p->to.type == D_MREG) { + p->mark |= LABEL|SYNC; + break; + } + if(p->from.type == D_FCREG || + p->from.type == D_MREG) { + p->mark |= LABEL|SYNC; + addnop(p); + addnop(p); + nop.mfrom.count += 2; + nop.mfrom.outof += 2; + break; + } + break; + + /* too hard, just leave alone */ + case ACASE: + case ASYSCALL: + case AWORD: + case ATLBWR: + case ATLBWI: + case ATLBP: + case ATLBR: + p->mark |= LABEL|SYNC; + break; + + case ANOR: + if(p->to.type == D_REG && p->to.reg == REGZERO) + p->mark |= LABEL|SYNC; + break; + + case ARET: + /* special form of RET is BECOME */ + if(p->from.type == D_CONST) + if(p->from.offset > curbecome) + curbecome = p->from.offset; + + if(p->link != P) + p->link->mark |= LABEL; + break; + + case ANOP: + q1 = p->link; + q->link = q1; /* q is non-nop */ + q1->mark |= p->mark; + continue; + + case ABCASE: + p->mark |= LABEL|SYNC; + goto dstlab; + + case ABGEZAL: + case ABLTZAL: + case AJAL: + if(curtext != P) + curtext->mark &= ~LEAF; + + case AJMP: + case ABEQ: + case ABGEZ: + case ABGTZ: + case ABLEZ: + case ABLTZ: + case ABNE: + case ABFPT: + case ABFPF: + p->mark |= BRANCH; + + dstlab: + q1 = p->cond; + if(q1 != P) { + while(q1->as == ANOP) { + q1 = q1->link; + p->cond = q1; + } + if(!(q1->mark & LEAF)) + q1->mark |= LABEL; + } else + p->mark |= LABEL; + q1 = p->link; + if(q1 != P) + q1->mark |= LABEL; + break; + } + q = p; + } + + if(curtext && curtext->from.sym) { + curtext->from.sym->frame = curframe; + curtext->from.sym->become = curbecome; + if(curbecome > maxbecome) + maxbecome = curbecome; + } + + if(debug['b']) + print("max become = %d\n", maxbecome); + xdefine("ALEFbecome", STEXT, maxbecome); + + curtext = 0; + for(p = firstp; p != P; p = p->link) { + switch(p->as) { + case ATEXT: + curtext = p; + break; + case AJAL: + if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { + o = maxbecome - curtext->from.sym->frame; + if(o <= 0) + break; + /* calling a become or calling a variable */ + if(p->to.sym == S || p->to.sym->become) { + curtext->to.offset += o; + if(debug['b']) { + curp = p; + print("%D calling %D increase %d\n", + &curtext->from, &p->to, o); + } + } + } + break; + } + } + + for(p = firstp; p != P; p = p->link) { + o = p->as; + switch(o) { + case ATEXT: + curtext = p; + autosize = p->to.offset + 4; + if(autosize <= 4) + if(curtext->mark & LEAF) { + p->to.offset = -4; + autosize = 0; + } + + q = p; + if(autosize) { + q = prg(); + q->as = AADD; + q->line = p->line; + q->from.type = D_CONST; + q->from.offset = -autosize; + q->to.type = D_REG; + q->to.reg = REGSP; + + q->link = p->link; + p->link = q; + } else + if(!(curtext->mark & LEAF)) { + if(debug['v']) + Bprint(&bso, "save suppressed in: %s\n", + curtext->from.sym->name); + Bflush(&bso); + curtext->mark |= LEAF; + } + + if(curtext->mark & LEAF) { + if(curtext->from.sym) + curtext->from.sym->type = SLEAF; + break; + } + + q1 = prg(); + q1->as = AMOVW; + q1->line = p->line; + q1->from.type = D_REG; + q1->from.reg = REGLINK; + q1->to.type = D_OREG; + q1->from.offset = 0; + q1->to.reg = REGSP; + + q1->link = q->link; + q->link = q1; + break; + + case ARET: + nocache(p); + if(p->from.type == D_CONST) + goto become; + if(curtext->mark & LEAF) { + if(!autosize) { + p->as = AJMP; + p->from = zprg.from; + p->to.type = D_OREG; + p->to.offset = 0; + p->to.reg = REGLINK; + p->mark |= BRANCH; + break; + } + + p->as = AADD; + p->from.type = D_CONST; + p->from.offset = autosize; + p->to.type = D_REG; + p->to.reg = REGSP; + + q = prg(); + q->as = AJMP; + q->line = p->line; + q->to.type = D_OREG; + q->to.offset = 0; + q->to.reg = REGLINK; + q->mark |= BRANCH; + + q->link = p->link; + p->link = q; + break; + } + p->as = AMOVW; + p->from.type = D_OREG; + p->from.offset = 0; + p->from.reg = REGSP; + p->to.type = D_REG; + p->to.reg = 2; + + q = p; + if(autosize) { + q = prg(); + q->as = AADD; + q->line = p->line; + q->from.type = D_CONST; + q->from.offset = autosize; + q->to.type = D_REG; + q->to.reg = REGSP; + + q->link = p->link; + p->link = q; + } + + q1 = prg(); + q1->as = AJMP; + q1->line = p->line; + q1->to.type = D_OREG; + q1->to.offset = 0; + q1->to.reg = 2; + q1->mark |= BRANCH; + + q1->link = q->link; + q->link = q1; + break; + + become: + if(curtext->mark & LEAF) { + + q = prg(); + q->line = p->line; + q->as = AJMP; + q->from = zprg.from; + q->to = p->to; + q->cond = p->cond; + q->link = p->link; + q->mark |= BRANCH; + p->link = q; + + p->as = AADD; + p->from = zprg.from; + p->from.type = D_CONST; + p->from.offset = autosize; + p->to = zprg.to; + p->to.type = D_REG; + p->to.reg = REGSP; + + break; + } + q = prg(); + q->line = p->line; + q->as = AJMP; + q->from = zprg.from; + q->to = p->to; + q->cond = p->cond; + q->link = p->link; + q->mark |= BRANCH; + p->link = q; + + q = prg(); + q->line = p->line; + q->as = AADD; + q->from.type = D_CONST; + q->from.offset = autosize; + q->to.type = D_REG; + q->to.reg = REGSP; + q->link = p->link; + p->link = q; + + p->as = AMOVW; + p->from = zprg.from; + p->from.type = D_OREG; + p->from.offset = 0; + p->from.reg = REGSP; + p->to = zprg.to; + p->to.type = D_REG; + p->to.reg = REGLINK; + + break; + } + } + + curtext = P; + q = P; /* p - 1 */ + q1 = firstp; /* top of block */ + o = 0; /* count of instructions */ + for(p = firstp; p != P; p = p1) { + p1 = p->link; + o++; + if(p->mark & NOSCHED){ + if(q1 != p){ + sched(q1, q); + } + for(; p != P; p = p->link){ + if(!(p->mark & NOSCHED)) + break; + q = p; + } + p1 = p; + q1 = p; + o = 0; + continue; + } + if(p->mark & (LABEL|SYNC)) { + if(q1 != p) + sched(q1, q); + q1 = p; + o = 1; + } + if(p->mark & (BRANCH|SYNC)) { + sched(q1, p); + q1 = p1; + o = 0; + } + if(o >= NSCHED) { + sched(q1, p); + q1 = p1; + o = 0; + } + q = p; + } +} + +void +addnop(Prog *p) +{ + Prog *q; + + q = prg(); + q->as = ANOR; + q->line = p->line; + q->from.type = D_REG; + q->from.reg = REGZERO; + q->to.type = D_REG; + q->to.reg = REGZERO; + + q->link = p->link; + p->link = q; +} + +void +nocache(Prog *p) +{ + p->optab = 0; + p->from.class = 0; + p->to.class = 0; +} |