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/7l/noop.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/7l/noop.c')
-rwxr-xr-x | sys/src/cmd/7l/noop.c | 947 |
1 files changed, 947 insertions, 0 deletions
diff --git a/sys/src/cmd/7l/noop.c b/sys/src/cmd/7l/noop.c new file mode 100755 index 000000000..e7f9b655b --- /dev/null +++ b/sys/src/cmd/7l/noop.c @@ -0,0 +1,947 @@ +#include "l.h" + +Prog *divuconst(Prog *, uvlong, int, int, int); +Prog *divconst(Prog *, vlong, int, int, int); +Prog *modconst(Prog *, vlong, int, int, int); +void excise(Prog *); + +void +noops(void) +{ + Prog *p, *p1, *q, *q1, *q2; + int o, curframe, curbecome, maxbecome, shift; + + /* + * find leaf subroutines + * become sizes + * frame sizes + * strip NOPs + * expand RET and other macros + * expand BECOME pseudo + * use conditional moves where appropriate + */ + + 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; + + /* don't mess with what we don't understand */ + case AWORD: + case ACALL_PAL: + /* etc. */ + p->mark |= LABEL; + for(q1=p->link; q1 != P; q1 = q1->link) { + q1->mark |= LABEL; + if(q1->as != AXORNOT) /* used as NOP in PALcode */ + break; + } + 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 AJSR: + if(curtext != P) + curtext->mark &= ~LEAF; + case ABEQ: + case ABNE: + case ABGE: + case ABGT: + case ABLE: + case ABLT: + case ABLBC: + case ABLBS: + case AFBEQ: + case AFBNE: + case AFBGE: + case AFBGT: + case AFBLE: + case AFBLT: + case AJMP: + p->mark |= BRANCH; + q1 = p->cond; + if(q1 != P) { + while(q1->as == ANOP) { + q1 = q1->link; + p->cond = q1; + } + if(!(q1->mark & LEAF)) { + if (q1->mark & LABEL) + q1->mark |= LABEL2; + else + q1->mark |= LABEL; + } + } else + p->mark |= LABEL; + q1 = p->link; + if(q1 != P) { + if (q1->mark & LABEL) + q1->mark |= LABEL2; + else + q1->mark |= LABEL; + } + else + p->mark |= LABEL; /* ??? */ + break; + + case ADIVQ: + case ADIVQU: + case AMODQ: + case AMODQU: + case ADIVL: + case ADIVLU: + case AMODL: + case AMODLU: + if(p->from.type == D_CONST /*&& !debug['d']*/) + continue; + if(prog_divq == P) + initdiv(); + if(curtext != P) + curtext->mark &= ~LEAF; + 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 AJSR: + 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 + 8; + if(autosize <= 8) + if(curtext->mark & LEAF) { + p->to.offset = -8; + autosize = 0; + } + if (autosize & 4) + autosize += 4; + + q = p; + if(autosize) + q = genIRR(p, ASUBQ, autosize, NREG, REGSP); + 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; + } + + genstore(q, AMOVL, REGLINK, 0LL, REGSP); + 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; + break; + } + + p->as = AADDQ; + 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 = AMOVL; + p->from.type = D_OREG; + p->from.offset = 0; + p->from.reg = REGSP; + p->to.type = D_REG; + p->to.reg = REGLINK; + + q = p; + if(autosize) + q = genIRR(p, AADDQ, autosize, NREG, REGSP); + + q1 = prg(); + q1->as = AJMP; + q1->line = p->line; + q1->to.type = D_OREG; + q1->to.offset = 0; + q1->to.reg = REGLINK; + 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 = AADDQ; + 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 = genIRR(p, AADDQ, autosize, NREG, REGSP); + + p->as = AMOVL; + 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; + + + /* All I wanted was a MOVB... */ + case AMOVB: + case AMOVW: + /* rewrite sign extend; could use v3 extension in asmout case 1 */ + if (p->to.type == D_REG) { + nocache(p); + shift = (p->as == AMOVB) ? (64-8) : (64-16); + if (p->from.type == D_REG) { + p->as = ASLLQ; + p->reg = p->from.reg; + p->from.type = D_CONST; + p->from.offset = shift; + q = genIRR(p, ASRAQ, shift, p->to.reg, p->to.reg); + break; + } + else { + p->as = (p->as == AMOVB) ? AMOVBU : AMOVWU; + q = genIRR(p, ASLLQ, shift, p->to.reg, p->to.reg); + q = genIRR(q, ASRAQ, shift, p->to.reg, p->to.reg); + } + } + /* fall through... */ + case AMOVBU: + case AMOVWU: + if(!debug['x']) + break; /* use BWX extension */ + o = p->as; + nocache(p); + if (p->from.type == D_OREG) { + if (p->to.type != D_REG) + break; + p->as = AMOVQU; + q = genXXX(p, AEXTBL, &p->to, REGTMP2, &p->to); + if (o == AMOVW || o == AMOVWU) + q->as = AEXTWL; + p->to.reg = REGTMP2; + if ((p->from.offset & 7) != 0 || aclass(&p->from) != C_SOREG) { + q1 = genXXX(p, AMOVA, &p->from, NREG, &q->to); + q1->from.offset &= 7; + q->from = q->to; + } + else + q->from.reg = p->from.reg; + if (o == AMOVB || o == AMOVW) + genXXX(q, o, &q->to, NREG, &q->to); + } + else if (p->to.type == D_OREG) { + if (aclass(&p->from) == C_ZCON) { + p->from.type = D_REG; + p->from.reg = REGZERO; + } + else if (p->from.type != D_REG) + break; + p->as = AMOVQU; + q = genRRR(p, AMSKBL, p->to.reg, REGTMP2, REGTMP2); + q1 = genRRR(q, AINSBL, p->to.reg, p->from.reg, REGTMP); + if (o == AMOVW || o == AMOVWU) { + q->as = AMSKWL; + q1->as = AINSWL; + } + q2 = genXXX(q1, AOR, &q->to, REGTMP, &q->to); + genXXX(q2, AMOVQU, &q->to, NREG, &p->to); + p->from = p->to; + p->to = q->to; + if ((p->from.offset & 7) != 0 || aclass(&p->from) != C_SOREG) { + q->from.reg = REGTMP; + q1->from.reg = REGTMP; + q = genXXX(p, AMOVA, &p->from, NREG, &q->from); + q->from.offset &= 7; + } + } + break; + + case ASLLL: + p->as = ASLLQ; + p = genXXX(p, AADDL, &p->to, REGZERO, &p->to); + break; + + case ASRLL: + if (p->to.type != D_REG) { + diag("illegal dest type in %P", p); + break; + } + if (p->reg == NREG) + p->reg = p->to.reg; + + q = genXXX(p, ASRLQ, &p->from, REGTMP, &p->to); + + p->as = AZAP; + p->from.type = D_CONST; + p->from.offset = 0xf0; + p->to.reg = REGTMP; + p = q; + + p = genXXX(p, AADDL, &p->to, REGZERO, &p->to); + break; + + case ASRAL: + p->as = ASRAQ; + break; + + case ADIVQ: + case ADIVQU: + case AMODQ: + case AMODQU: + case ADIVL: + case ADIVLU: + case AMODL: + case AMODLU: + /* if (debug['d']) + print("%P\n", p); */ + if(p->to.type != D_REG) + break; + /*if(debug['d'] && p->from.type == D_CONST) { + q = genRRR(p, p->as, REGTMP, p->reg, p->to.reg); + p->as = AMOVQ; + p->reg = NREG; + p->to.reg = REGTMP; + p = q; + }*/ + if(p->from.type == D_CONST) { + if (p->reg == NREG) + p->reg = p->to.reg; + switch (p->as) { + case ADIVQ: + q = divconst(p, p->from.offset, p->reg, p->to.reg, 64); + break; + case ADIVQU: + q = divuconst(p, p->from.offset, p->reg, p->to.reg, 64); + break; + case AMODQ: + q = modconst(p, p->from.offset, p->reg, p->to.reg, 64); + break; + case AMODQU: + q = divuconst(p, p->from.offset, p->reg, REGTMP2, 64); + q = genIRR(q, AMULQ, p->from.offset, REGTMP2, REGTMP2); + q = genRRR(q, ASUBQ, REGTMP2, p->reg, p->to.reg); + break; + case ADIVL: + q = divconst(p, p->from.offset, p->reg, p->to.reg, 32); + break; + case ADIVLU: + q = divuconst(p, p->from.offset, p->reg, p->to.reg, 32); + break; + case AMODL: + q = modconst(p, p->from.offset, p->reg, p->to.reg, 32); + break; + case AMODLU: + q = divuconst(p, p->from.offset, p->reg, REGTMP2, 32); + q = genIRR(q, AMULQ, p->from.offset, REGTMP2, REGTMP2); + q = genRRR(q, ASUBQ, REGTMP2, p->reg, p->to.reg); + break; + } + excise(p); + p = q; + break; + } + if(p->from.type != D_REG){ + diag("bad instruction %P", p); + break; + } + o = p->as; + q = genIRR(p, ASUBQ, 16LL, NREG, REGSP); + q = genstore(q, AMOVQ, p->from.reg, 8LL, REGSP); + if (o == ADIVL || o == ADIVL || o == AMODL || o == AMODLU) + q->as = AMOVL; + + q = genRRR(q, AMOVQ, p->reg, NREG, REGTMP); + if (p->reg == NREG) + q->from.reg = p->to.reg; + + /* CALL appropriate */ + q1 = prg(); + q1->link = q->link; + q->link = q1; + + q1->as = AJSR; + q1->line = p->line; + q1->to.type = D_BRANCH; + q1->cond = divsubr(o); + q1->mark |= BRANCH; + q = q1; + + q = genRRR(q, AMOVQ, REGTMP, NREG, p->to.reg); + q = genIRR(q, AADDQ, 16LL, NREG, REGSP); + excise(p); + p = q; + break; + + /* Attempt to replace {cond. branch, mov} with a cmov */ + /* XXX warning: this is all a bit experimental */ + case ABEQ: + case ABNE: + case ABGE: + case ABGT: + case ABLE: + case ABLT: + case ABLBC: + case ABLBS: + q = p->link; + if (q == P) + break; + q1 = q->link; + if (q1 != p->cond || q1 == P) + break; +/*print("%P\n", q); /* */ + if (q->to.type != D_REG) + break; + if (q->from.type != D_REG && (q->from.type != D_CONST || q->from.name != D_NONE)) + break; + if (q->mark&LABEL2) + break; +/* print("%P\n", q); /* */ + if (q->as != AMOVQ) /* XXX can handle more than this! */ + break; + q->as = (p->as^1) + ACMOVEQ-ABEQ; /* sleazy hack */ + q->reg = p->from.reg; /* XXX check CMOVx operand order! */ + excise(p); /* XXX p's LABEL? */ + if (!(q1->mark&LABEL2)) + q1->mark &= ~LABEL; + break; + case AFBEQ: + case AFBNE: + case AFBGE: + case AFBGT: + case AFBLE: + case AFBLT: + q = p->link; + if (q == P) + break; + q1 = q->link; + if (q1 != p->cond || q1 == P) + break; + if (q->from.type != D_FREG || q->to.type != D_FREG) + break; +/* print("%P\n", q); /* */ + if (q->mark&LABEL2) + break; + if (q->as != AMOVT) /* XXX can handle more than this! */ + break; + q->as = (p->as^1) + AFCMOVEQ-AFBEQ; /* sleazy hack */ + q->reg = p->from.reg; /* XXX check CMOVx operand order! */ + excise(p); /* XXX p's LABEL? */ + if (!(q1->mark&LABEL2)) + q1->mark &= ~LABEL; + 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 +nocache(Prog *p) +{ + p->optab = 0; + p->from.class = 0; + p->to.class = 0; +} + +/* XXX use of this may lose important LABEL flags, check that this isn't happening (or fix) */ +void +excise(Prog *p) +{ + Prog *q; + + q = p->link; + *p = *q; +} + +void +initdiv(void) +{ + Sym *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8; + Prog *p; + + s1 = lookup("_divq", 0); + s2 = lookup("_divqu", 0); + s3 = lookup("_modq", 0); + s4 = lookup("_modqu", 0); + s5 = lookup("_divl", 0); + s6 = lookup("_divlu", 0); + s7 = lookup("_modl", 0); + s8 = lookup("_modlu", 0); + for(p = firstp; p != P; p = p->link) + if(p->as == ATEXT) { + if(p->from.sym == s1) + prog_divq = p; + if(p->from.sym == s2) + prog_divqu = p; + if(p->from.sym == s3) + prog_modq = p; + if(p->from.sym == s4) + prog_modqu = p; + if(p->from.sym == s5) + prog_divl = p; + if(p->from.sym == s6) + prog_divlu = p; + if(p->from.sym == s7) + prog_modl = p; + if(p->from.sym == s8) + prog_modlu = p; + } + if(prog_divq == P) { + diag("undefined: %s", s1->name); + prog_divq = curtext; + } + if(prog_divqu == P) { + diag("undefined: %s", s2->name); + prog_divqu = curtext; + } + if(prog_modq == P) { + diag("undefined: %s", s3->name); + prog_modq = curtext; + } + if(prog_modqu == P) { + diag("undefined: %s", s4->name); + prog_modqu = curtext; + } + if(prog_divl == P) { + diag("undefined: %s", s5->name); + prog_divl = curtext; + } + if(prog_divlu == P) { + diag("undefined: %s", s6->name); + prog_divlu = curtext; + } + if(prog_modl == P) { + diag("undefined: %s", s7->name); + prog_modl = curtext; + } + if(prog_modlu == P) { + diag("undefined: %s", s8->name); + prog_modlu = curtext; + } +} + +Prog * +divsubr(int o) +{ + switch(o) { + case ADIVQ: + return prog_divq; + case ADIVQU: + return prog_divqu; + case AMODQ: + return prog_modq; + case AMODQU: + return prog_modqu; + case ADIVL: + return prog_divl; + case ADIVLU: + return prog_divlu; + case AMODL: + return prog_modl; + case AMODLU: + return prog_modlu; + default: + diag("bad op %A in divsubr", o); + return prog_modlu; + } +} + +Prog* +divuconst(Prog *p, uvlong y, int num, int quot, int bits) +{ + int logy, i, shift; + uvlong k, m, n, mult, tmp, msb; + + if(num == NREG) + num = quot; + if(y == 0) { + diag("division by zero"); + return p; + } + if(y == 1) + return genRRR(p, AMOVQ, num, NREG, quot); + + if(num == REGTMP || quot == REGTMP) + diag("bad register in divuconst"); + + tmp = y; + for(logy = -1; tmp != 0; logy++) + tmp >>= 1; + + msb = (1LL << (bits-1)); + if((y & (y-1)) == 0) /* power of 2 */ + return genIRR(p, ASRLQ, logy, num, quot); + if(y > msb) + return genIRR(p, ACMPUGE, y, num, quot); + + /* k = (-2^(bits+logy)) % y */ + m = msb/y; + n = msb%y; + if(debug['d']) + Bprint(&bso, "divuconst: y=%lld msb=%lld m=%lld n=%lld\n", + y, msb, m, n); + for(i = 0; i <= logy; i++) { + m *= 2LL; + n *= 2LL; + if(n > y) { + m += 1LL; + n -= y; + } + } + if(debug['d']) + Bprint(&bso, "divuconst: y=%lld msb=%lld m=%lld n=%lld\n", + y, msb, m, n); + k = y - n; + if(k > (1LL << logy)) { + mult = 2LL*m + 1LL; + bits++; + } else + mult = m + 1LL; + + shift = bits + logy; + if(debug['d']) + Bprint(&bso, "divuconst: y=%lld mult=%lld shift=%d bits=%d k=%lld\n", + y, mult, shift, bits, k); + if(bits <= 32) { + p = genIRR(p, AMOVQ, mult, NREG, REGTMP); + p = genRRR(p, AEXTLL, REGZERO, num, quot); + p = genRRR(p, AMULQ, REGTMP, quot, quot); + p = genIRR(p, ASRLQ, shift, quot, quot); + p = genRRR(p, AADDL, quot, REGZERO, quot); + return p; + } + if(bits == 33) { + if(shift < 64) { + mult <<= (64-shift); + shift = 64; + } + p = genIRR(p, AMOVQ, mult, NREG, REGTMP); + p = genRRR(p, AEXTLL, REGZERO, num, quot); + p = genRRR(p, AUMULH, REGTMP, quot, quot); + if(shift != 64) + p = genIRR(p, ASRLQ, shift-64, quot, quot); + p = genRRR(p, AADDL, quot, REGZERO, quot); + return p; + } + if(bits <= 64) { + if(shift < 64) { + mult <<= (64-shift); + shift = 64; + } + p = genIRR(p, AMOVQ, mult, NREG, REGTMP); + p = genRRR(p, AUMULH, REGTMP, num, quot); + if(shift != 64) + p = genIRR(p, ASRLQ, shift-64, quot, quot); + return p; + } + + p = genIRR(p, AMOVQ, mult, NREG, REGTMP); + p = genRRR(p, AUMULH, REGTMP, num, REGTMP); + p = genRRR(p, AADDQ, num, REGTMP, quot); + p = genRRR(p, ACMPUGT, REGTMP, quot, REGTMP); + p = genIRR(p, ASLLQ, 128-shift, REGTMP, REGTMP); + p = genIRR(p, ASRLQ, shift-64, quot, quot); + p = genRRR(p, AADDQ, REGTMP, quot, quot); + return p; +} + +Prog * +divconst(Prog *p, vlong y, int num, int quot, int bits) +{ + vlong yabs; + Prog *q; + + yabs = y; + if (y < 0) + yabs = -y; + q = genRRR(p, ASUBQ, num, REGZERO, REGTMP2); + if (num != quot) + q = genRRR(q, AMOVQ, num, NREG, quot); + q = genRRR(q, ACMOVGT, REGTMP2, REGTMP2, quot); + q = divuconst(q, yabs, quot, quot, bits-1); + q = genRRR(q, ASUBQ, quot, REGZERO, REGTMP); + q = genRRR(q, (y < 0)? ACMOVLT: ACMOVGT, REGTMP, REGTMP2, quot); + return q; +} + +Prog * +modconst(Prog *p, vlong y, int num, int quot, int bits) +{ + vlong yabs; + Prog *q; + + yabs = y; + if (y < 0) + yabs = -y; + q = genRRR(p, ASUBQ, num, REGZERO, REGTMP2); + q = genRRR(q, ACMOVLT, num, REGTMP2, REGTMP2); + q = divuconst(q, yabs, REGTMP2, REGTMP2, bits-1); + q = genRRR(q, ASUBQ, REGTMP2, REGZERO, REGTMP); + q = genRRR(q, ACMOVLT, REGTMP, num, REGTMP2); + q = genIRR(q, AMULQ, yabs, REGTMP2, REGTMP2); + q = genRRR(q, ASUBQ, REGTMP2, num, quot); + return q; +} + +Prog * +genXXX(Prog *q, int op, Adr *from, int reg, Adr *to) +{ + Prog *p; + + p = prg(); + p->as = op; + p->line = q->line; + p->from = *from; + p->to = *to; + p->reg = reg; + p->link = q->link; + q->link = p; + return p; +} + +Prog * +genRRR(Prog *q, int op, int from, int reg, int to) +{ + Prog *p; + + p = prg(); + p->as = op; + p->line = q->line; + p->from.type = D_REG; + p->from.reg = from; + p->to.type = D_REG; + p->to.reg = to; + p->reg = reg; + p->link = q->link; + q->link = p; + return p; +} + +Prog * +genIRR(Prog *q, int op, vlong v, int reg, int to) +{ + Prog *p; + + p = prg(); + p->as = op; + p->line = q->line; + p->from.type = D_CONST; + p->from.offset = v; + p->to.type = D_REG; + p->to.reg = to; + p->reg = reg; + p->link = q->link; + q->link = p; + return p; +} + +Prog * +genstore(Prog *q, int op, int from, vlong offset, int to) +{ + Prog *p; + + p = prg(); + p->as = op; + p->line = q->line; + p->from.type = D_REG; + p->from.reg = from; + p->to.type = D_OREG; + p->to.reg = to; + p->to.offset = offset; + p->reg = NREG; + p->link = q->link; + q->link = p; + return p; +} + +Prog * +genload(Prog *q, int op, vlong offset, int from, int to) +{ + Prog *p; + + p = prg(); + p->as = op; + p->line = q->line; + p->from.type = D_OREG; + p->from.offset = offset; + p->from.reg = from; + p->to.type = D_REG; + p->to.reg = to; + p->reg = NREG; + p->link = q->link; + q->link = p; + return p; +} |