#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;
+ Prog *p, *q, *q1;
+ int o, aoffset, curframe, curbecome, maxbecome;
/*
* find leaf subroutines
* become sizes
* frame sizes
* strip NOPs
- * expand RET and other macros
+ * expand RET
* expand BECOME pseudo
- * use conditional moves where appropriate
*/
if(debug['v'])
curframe = 0;
curbecome = 0;
- p->mark |= LABEL|LEAF|SYNC;
- if(p->link)
- p->link->mark |= LABEL;
+ p->mark |= LEAF;
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 */
+ case ARETURN:
+ /* special form of RETURN 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->mark |= p->mark;
continue;
- case AJSR:
+ case ABL:
if(curtext != P)
curtext->mark &= ~LEAF;
+
+ case ACBNZ:
+ case ACBZ:
+ case ACBNZW:
+ case ACBZW:
+ case ATBZ:
+ case ATBNZ:
+
+ case ABCASE:
+ case AB:
+
case ABEQ:
case ABNE:
+ case ABCS:
+ case ABHS:
+ case ABCC:
+ case ABLO:
+ case ABMI:
+ case ABPL:
+ case ABVS:
+ case ABVC:
+ case ABHI:
+ case ABLS:
case ABGE:
+ case ABLT:
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;
+
+ case AADR: /* strange */
+ case AADRP:
+
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;
case ATEXT:
curtext = p;
break;
- case AJSR:
+ case ABL:
if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
o = maxbecome - curtext->from.sym->frame;
if(o <= 0)
switch(o) {
case ATEXT:
curtext = p;
- autosize = p->to.offset + 8;
- if(autosize <= 8)
- if(curtext->mark & LEAF) {
- p->to.offset = -8;
+ if(p->to.offset < 0)
autosize = 0;
- }
- if (autosize & 4)
- autosize += 4;
+ else
+ autosize = p->to.offset + PCSZ;
+ if((curtext->mark & LEAF) && autosize <= PCSZ)
+ autosize = 0;
+ else if(autosize & (STACKALIGN-1))
+ autosize += STACKALIGN - (autosize&(STACKALIGN-1));
+ p->to.offset = autosize - PCSZ;
- q = p;
- if(autosize)
- q = genIRR(p, ASUBQ, autosize, NREG, REGSP);
- else if(!(curtext->mark & LEAF)) {
+ if(autosize == 0 && !(curtext->mark & LEAF)) {
if(debug['v'])
Bprint(&bso, "save suppressed in: %s\n",
curtext->from.sym->name);
curtext->mark |= LEAF;
}
+ aoffset = autosize;
+ if(aoffset > 0xF0)
+ aoffset = 0xF0;
+
if(curtext->mark & LEAF) {
if(curtext->from.sym)
curtext->from.sym->type = SLEAF;
- break;
+ if(autosize == 0)
+ break;
+ aoffset = 0;
}
- genstore(q, AMOVL, REGLINK, 0LL, REGSP);
+ q = p;
+ if(autosize > aoffset){
+ q = prg();
+ q->as = ASUB;
+ q->line = p->line;
+ q->from.type = D_CONST;
+ q->from.offset = autosize - aoffset;
+ q->to.type = D_REG;
+ q->to.reg = REGSP;
+ q->link = p->link;
+ p->link = q;
+
+ if(curtext->mark & LEAF)
+ break;
+ }
+
+ q1 = prg();
+ q1->as = AMOV;
+ q1->line = p->line;
+ q1->from.type = D_REG;
+ q1->from.reg = REGLINK;
+ q1->to.type = D_XPRE;
+ q1->to.offset = -aoffset;
+ q1->to.reg = REGSP;
+
+ q1->link = q->link;
+ q->link = q1;
break;
- case ARET:
+ case ARETURN:
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;
+ if(autosize != 0){
+ p->as = AADD;
+ p->from.type = D_CONST;
+ p->from.offset = autosize;
+ p->to.type = D_REG;
+ p->to.reg = REGSP;
}
-
- p->as = AADDQ;
- p->from.type = D_CONST;
- p->from.offset = autosize;
+ }else{
+ /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
+ aoffset = autosize;
+ if(aoffset > 0xF0)
+ aoffset = 0xF0;
+
+ p->as = AMOV;
+ p->from.type = D_XPOST;
+ p->from.offset = aoffset;
+ p->from.reg = REGSP;
p->to.type = D_REG;
- p->to.reg = REGSP;
+ p->to.reg = REGLINK;
+
+ if(autosize > aoffset) {
+ q = prg();
+ q->as = AADD;
+ q->from.type = D_CONST;
+ q->from.offset = autosize - aoffset;
+ q->to.type = D_REG;
+ q->to.reg = REGSP;
+
+ q->link = p->link;
+ p->link = q;
+ p = q;
+ }
+ }
+ if(p->as != ARETURN) {
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 = q;
}
- 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;
+ p->as = ARET;
+ p->line = p->line;
+ p->to.type = D_OREG;
+ p->to.offset = 0;
+ p->to.reg = REGLINK;
- q1->link = q->link;
- q->link = q1;
break;
become:
if(curtext->mark & LEAF) {
+ if(!autosize) {
+ p->as = AB;
+ p->from = zprg.from;
+ break;
+ }
+
+#ifdef optimise_time
q = prg();
q->line = p->line;
- q->as = AJMP;
+ q->as = AB;
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->as = AADD;
p->from = zprg.from;
p->from.type = D_CONST;
p->from.offset = autosize;
p->to.reg = REGSP;
break;
+#endif
}
q = prg();
q->line = p->line;
- q->as = AJMP;
+ q->as = AB;
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->as = AMOV;
p->from = zprg.from;
- p->from.type = D_OREG;
- p->from.offset = 0;
+ p->from.type = D_XPRE;
+ p->from.offset = -autosize;
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;
}
}
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;
-}