summaryrefslogtreecommitdiff
path: root/6/isel.c
diff options
context:
space:
mode:
Diffstat (limited to '6/isel.c')
-rw-r--r--6/isel.c1744
1 files changed, 872 insertions, 872 deletions
diff --git a/6/isel.c b/6/isel.c
index 18b0e78..356bdca 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -22,244 +22,244 @@ Loc *selexpr(Isel *s, Node *n);
#define Nfloatregargs 8
#define Nintregargs 6
regid floatargregs[] = {
- Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
- Rxmm4d, Rxmm5d, Rxmm6d, Rxmm7d,
+ Rxmm0d, Rxmm1d, Rxmm2d, Rxmm3d,
+ Rxmm4d, Rxmm5d, Rxmm6d, Rxmm7d,
};
regid intargregs[] = {Rrdi, Rrsi, Rrdx, Rrcx, Rr8, Rr9};
/* used to decide which operator is appropriate
* for implementing various conditional operators */
struct {
- AsmOp test;
- AsmOp jmp;
- AsmOp getflag;
+ AsmOp test;
+ AsmOp jmp;
+ AsmOp getflag;
} reloptab[Numops] = {
- [Olnot] = {Itest, Ijz, Isetz}, /* lnot invalid for floats */
- /* signed int */
- [Oeq] = {Icmp, Ijz, Isetz},
- [One] = {Icmp, Ijnz, Isetnz},
- [Ogt] = {Icmp, Ijg, Isetg},
- [Oge] = {Icmp, Ijge, Isetge},
- [Olt] = {Icmp, Ijl, Isetl},
- [Ole] = {Icmp, Ijle, Isetle},
- /* unsigned int */
- [Oueq] = {Icmp, Ijz, Isetz},
- [Oune] = {Icmp, Ijnz, Isetnz},
- [Ougt] = {Icmp, Ija, Iseta},
- [Ouge] = {Icmp, Ijae, Isetae},
- [Oult] = {Icmp, Ijb, Isetb},
- [Oule] = {Icmp, Ijbe, Isetbe},
- /* float */
- [Ofeq] = {Icomis, Ijz, Isetz},
- [Ofne] = {Icomis, Ijnz, Isetnz},
- [Ofgt] = {Icomis, Ija, Iseta},
- [Ofge] = {Icomis, Ijae, Isetae},
- [Oflt] = {Icomis, Ijb, Isetb},
- [Ofle] = {Icomis, Ijbe, Isetbe},
+ [Olnot] = {Itest, Ijz, Isetz}, /* lnot invalid for floats */
+ /* signed int */
+ [Oeq] = {Icmp, Ijz, Isetz},
+ [One] = {Icmp, Ijnz, Isetnz},
+ [Ogt] = {Icmp, Ijg, Isetg},
+ [Oge] = {Icmp, Ijge, Isetge},
+ [Olt] = {Icmp, Ijl, Isetl},
+ [Ole] = {Icmp, Ijle, Isetle},
+ /* unsigned int */
+ [Oueq] = {Icmp, Ijz, Isetz},
+ [Oune] = {Icmp, Ijnz, Isetnz},
+ [Ougt] = {Icmp, Ija, Iseta},
+ [Ouge] = {Icmp, Ijae, Isetae},
+ [Oult] = {Icmp, Ijb, Isetb},
+ [Oule] = {Icmp, Ijbe, Isetbe},
+ /* float */
+ [Ofeq] = {Icomis, Ijz, Isetz},
+ [Ofne] = {Icomis, Ijnz, Isetnz},
+ [Ofgt] = {Icomis, Ija, Iseta},
+ [Ofge] = {Icomis, Ijae, Isetae},
+ [Oflt] = {Icomis, Ijb, Isetb},
+ [Ofle] = {Icomis, Ijbe, Isetbe},
};
static Mode tymode(Type *t)
{
- /* FIXME: What should the mode for, say, structs be when we have no
- * intention of loading /through/ the pointer? For now, we'll just say it's
- * the pointer mode, since we expect to address through the pointer */
- t = tybase(t);
- switch (t->type) {
- case Tyflt32: return ModeF; break;
- case Tyflt64: return ModeD; break;
- default:
- if (isstacktype(t))
- return ModeQ;
- switch (tysize(t)) {
- case 1: return ModeB; break;
- case 2: return ModeW; break;
- case 4: return ModeL; break;
- case 8: return ModeQ; break;
- }
- break;
- }
- return ModeQ;
+ /* FIXME: What should the mode for, say, structs be when we have no
+ * intention of loading /through/ the pointer? For now, we'll just say it's
+ * the pointer mode, since we expect to address through the pointer */
+ t = tybase(t);
+ switch (t->type) {
+ case Tyflt32: return ModeF; break;
+ case Tyflt64: return ModeD; break;
+ default:
+ if (isstacktype(t))
+ return ModeQ;
+ switch (tysize(t)) {
+ case 1: return ModeB; break;
+ case 2: return ModeW; break;
+ case 4: return ModeL; break;
+ case 8: return ModeQ; break;
+ }
+ break;
+ }
+ return ModeQ;
}
static Mode mode(Node *n)
{
- if (n->type == Nexpr)
- return tymode(exprtype(n));
- else if (n->type == Ndecl)
- return tymode(n->decl.type);
- else
- die("invalid node type");
- return ModeNone;
+ if (n->type == Nexpr)
+ return tymode(exprtype(n));
+ else if (n->type == Ndecl)
+ return tymode(n->decl.type);
+ else
+ die("invalid node type");
+ return ModeNone;
}
static Loc *varloc(Isel *s, Node *n)
{
- ssize_t off;
- Loc *l, *rip;
-
- /* we need to try getting it from the stack first, in case we
- * forced it to stack for addressing */
- if (hthas(s->globls, n)) {
- rip = locphysreg(Rrip);
- l = locmeml(htget(s->globls, n), rip, NULL, mode(n));
- } else if (hthas(s->envoff, n)) {
- off = ptoi(htget(s->envoff, n));
- l = locmem(off, s->envp, NULL, mode(n));
- } else if (hthas(s->stkoff, n)) {
- off = ptoi(htget(s->stkoff, n));
- l = locmem(-off, locphysreg(Rrbp), NULL, mode(n));
- } else {
- l = htget(s->reglocs, n);
- if (!l) {
- l = locreg(mode(n));
- htput(s->reglocs, n, l);
- }
- }
- return l;
+ ssize_t off;
+ Loc *l, *rip;
+
+ /* we need to try getting it from the stack first, in case we
+ * forced it to stack for addressing */
+ if (hthas(s->globls, n)) {
+ rip = locphysreg(Rrip);
+ l = locmeml(htget(s->globls, n), rip, NULL, mode(n));
+ } else if (hthas(s->envoff, n)) {
+ off = ptoi(htget(s->envoff, n));
+ l = locmem(off, s->envp, NULL, mode(n));
+ } else if (hthas(s->stkoff, n)) {
+ off = ptoi(htget(s->stkoff, n));
+ l = locmem(-off, locphysreg(Rrbp), NULL, mode(n));
+ } else {
+ l = htget(s->reglocs, n);
+ if (!l) {
+ l = locreg(mode(n));
+ htput(s->reglocs, n, l);
+ }
+ }
+ return l;
}
static Loc *loc(Isel *s, Node *n)
{
- Node *v;
- Loc *l;
-
- if (n->type == Ndecl) {
- l = varloc(s, n);
- } else {
- switch (exprop(n)) {
- case Ovar:
- l = varloc(s, n);
- break;
- case Olit:
- v = n->expr.args[0];
- switch (v->lit.littype) {
- case Lchr: l = loclit(v->lit.chrval, mode(n)); break;
- case Lbool: l = loclit(v->lit.boolval, mode(n)); break;
- case Lint: l = loclit(v->lit.intval, mode(n)); break;
- default:
- die("Literal type %s should be blob", litstr[v->lit.littype]);
- }
- break;
- default:
- die("Node %s not leaf in loc()", opstr[exprop(n)]);
- break;
- }
- }
- return l;
+ Node *v;
+ Loc *l;
+
+ if (n->type == Ndecl) {
+ l = varloc(s, n);
+ } else {
+ switch (exprop(n)) {
+ case Ovar:
+ l = varloc(s, n);
+ break;
+ case Olit:
+ v = n->expr.args[0];
+ switch (v->lit.littype) {
+ case Lchr: l = loclit(v->lit.chrval, mode(n)); break;
+ case Lbool: l = loclit(v->lit.boolval, mode(n)); break;
+ case Lint: l = loclit(v->lit.intval, mode(n)); break;
+ default:
+ die("Literal type %s should be blob", litstr[v->lit.littype]);
+ }
+ break;
+ default:
+ die("Node %s not leaf in loc()", opstr[exprop(n)]);
+ break;
+ }
+ }
+ return l;
}
static Insn *mkinsnv(AsmOp op, va_list ap)
{
- Loc *l;
- Insn *i;
- int n;
- static size_t insnid;
-
- n = 0;
- i = malloc(sizeof(Insn));
- i->op = op;
- i->uid = insnid++;
- while ((l = va_arg(ap, Loc*)) != NULL)
- i->args[n++] = l;
- i->nargs = n;
- return i;
+ Loc *l;
+ Insn *i;
+ int n;
+ static size_t insnid;
+
+ n = 0;
+ i = malloc(sizeof(Insn));
+ i->op = op;
+ i->uid = insnid++;
+ while ((l = va_arg(ap, Loc*)) != NULL)
+ i->args[n++] = l;
+ i->nargs = n;
+ return i;
}
Insn *mkinsn(AsmOp op, ...)
{
- va_list ap;
- Insn *i;
+ va_list ap;
+ Insn *i;
- va_start(ap, op);
- i = mkinsnv(op, ap);
- va_end(ap);
- return i;
+ va_start(ap, op);
+ i = mkinsnv(op, ap);
+ va_end(ap);
+ return i;
}
static void g(Isel *s, AsmOp op, ...)
{
- va_list ap;
- Insn *i;
-
- va_start(ap, op);
- i = mkinsnv(op, ap);
- va_end(ap);
- if (debugopt['i']) {
- printf("GEN[uid=%zd] ", i->uid);
- dbgiprintf(stdout, i);
- }
- lappend(&s->curbb->il, &s->curbb->ni, i);
+ va_list ap;
+ Insn *i;
+
+ va_start(ap, op);
+ i = mkinsnv(op, ap);
+ va_end(ap);
+ if (debugopt['i']) {
+ printf("GEN[uid=%zd] ", i->uid);
+ dbgiprintf(stdout, i);
+ }
+ lappend(&s->curbb->il, &s->curbb->ni, i);
}
static void movz(Isel *s, Loc *src, Loc *dst)
{
- if (src->mode == dst->mode)
- g(s, Imov, src, dst, NULL);
- else
- g(s, Imovzx, src, dst, NULL);
+ if (src->mode == dst->mode)
+ g(s, Imov, src, dst, NULL);
+ else
+ g(s, Imovzx, src, dst, NULL);
}
static void load(Isel *s, Loc *a, Loc *b)
{
- Loc *l;
-
- assert(b->type == Locreg);
- if (a->type == Locreg)
- l = locmem(0, b, NULL, a->mode);
- else
- l = a;
- if (isfloatmode(b->mode))
- g(s, Imovs, l, b, NULL);
- else
- g(s, Imov, l, b, NULL);
+ Loc *l;
+
+ assert(b->type == Locreg);
+ if (a->type == Locreg)
+ l = locmem(0, b, NULL, a->mode);
+ else
+ l = a;
+ if (isfloatmode(b->mode))
+ g(s, Imovs, l, b, NULL);
+ else
+ g(s, Imov, l, b, NULL);
}
static void stor(Isel *s, Loc *a, Loc *b)
{
- Loc *l;
-
- assert(a->type == Locreg || a->type == Loclit);
- if (b->type == Locreg)
- l = locmem(0, b, NULL, b->mode);
- else
- l = b;
- if (isfloatmode(b->mode))
- g(s, Imovs, a, l, NULL);
- else
- g(s, Imov, a, l, NULL);
+ Loc *l;
+
+ assert(a->type == Locreg || a->type == Loclit);
+ if (b->type == Locreg)
+ l = locmem(0, b, NULL, b->mode);
+ else
+ l = b;
+ if (isfloatmode(b->mode))
+ g(s, Imovs, a, l, NULL);
+ else
+ g(s, Imov, a, l, NULL);
}
/* ensures that a location is within a reg */
static Loc *newr(Isel *s, Loc *a)
{
- Loc *r;
-
- r = locreg(a->mode);
- if (a->type == Locreg) {
- if (isfloatmode(a->mode))
- g(s, Imovs, a, r, NULL);
- else
- g(s, Imov, a, r, NULL);
- } else {
- load(s, a, r);
- }
- return r;
+ Loc *r;
+
+ r = locreg(a->mode);
+ if (a->type == Locreg) {
+ if (isfloatmode(a->mode))
+ g(s, Imovs, a, r, NULL);
+ else
+ g(s, Imov, a, r, NULL);
+ } else {
+ load(s, a, r);
+ }
+ return r;
}
static Loc *inr(Isel *s, Loc *a)
{
- if (a->type == Locreg)
- return a;
- return newr(s, a);
+ if (a->type == Locreg)
+ return a;
+ return newr(s, a);
}
/* ensures that a location is within a reg or an imm */
static Loc *inri(Isel *s, Loc *a)
{
- if (a->type == Locreg || a->type == Loclit)
- return a;
- else
- return newr(s, a);
+ if (a->type == Locreg || a->type == Loclit)
+ return a;
+ else
+ return newr(s, a);
}
/* If we're testing equality, etc, it's a bit silly
@@ -273,35 +273,35 @@ static Loc *inri(Isel *s, Loc *a)
* directly */
static void selcjmp(Isel *s, Node *n, Node **args)
{
- Loc *a, *b;
- Loc *l1, *l2;
- AsmOp cond, jmp;
-
- cond = reloptab[exprop(args[0])].test;
- jmp = reloptab[exprop(args[0])].jmp;
- /* if we have a cond, we're knocking off the redundant test,
- * and want to eval the children */
- if (cond) {
- a = selexpr(s, args[0]->expr.args[0]);
- if (args[0]->expr.nargs == 2)
- b = selexpr(s, args[0]->expr.args[1]);
- else
- b = a;
- a = newr(s, a);
- } else {
- cond = Itest;
- jmp = Ijnz;
- b = newr(s, selexpr(s, args[0])); /* cond */
- a = b;
- }
-
- /* the jump targets will always be evaluated the same way */
- l1 = loclbl(args[1]); /* if true */
- l2 = loclbl(args[2]); /* if false */
-
- g(s, cond, b, a, NULL);
- g(s, jmp, l1, NULL);
- g(s, Ijmp, l2, NULL);
+ Loc *a, *b;
+ Loc *l1, *l2;
+ AsmOp cond, jmp;
+
+ cond = reloptab[exprop(args[0])].test;
+ jmp = reloptab[exprop(args[0])].jmp;
+ /* if we have a cond, we're knocking off the redundant test,
+ * and want to eval the children */
+ if (cond) {
+ a = selexpr(s, args[0]->expr.args[0]);
+ if (args[0]->expr.nargs == 2)
+ b = selexpr(s, args[0]->expr.args[1]);
+ else
+ b = a;
+ a = newr(s, a);
+ } else {
+ cond = Itest;
+ jmp = Ijnz;
+ b = newr(s, selexpr(s, args[0])); /* cond */
+ a = b;
+ }
+
+ /* the jump targets will always be evaluated the same way */
+ l1 = loclbl(args[1]); /* if true */
+ l2 = loclbl(args[2]); /* if false */
+
+ g(s, cond, b, a, NULL);
+ g(s, jmp, l1, NULL);
+ g(s, Ijmp, l2, NULL);
}
/* Generate variable length jump. There are 3 cases
@@ -320,13 +320,13 @@ static void selvjmp(Isel *s, Node *n, Node **args)
static Loc *binop(Isel *s, AsmOp op, Node *x, Node *y)
{
- Loc *a, *b;
+ Loc *a, *b;
- a = selexpr(s, x);
- b = selexpr(s, y);
- a = newr(s, a);
- g(s, op, b, a, NULL);
- return a;
+ a = selexpr(s, x);
+ b = selexpr(s, y);
+ a = newr(s, a);
+ g(s, op, b, a, NULL);
+ return a;
}
/* We have a few common cases to optimize here:
@@ -344,723 +344,723 @@ static Loc *binop(Isel *s, AsmOp op, Node *x, Node *y)
*/
static int ismergablemul(Node *n, int *r)
{
- int v;
-
- if (exprop(n) != Omul)
- return 0;
- if (exprop(n->expr.args[1]) != Olit)
- return 0;
- if (n->expr.args[1]->expr.args[0]->type != Nlit)
- return 0;
- if (n->expr.args[1]->expr.args[0]->lit.littype != Lint)
- return 0;
- v = n->expr.args[1]->expr.args[0]->lit.intval;
- if (v != 2 && v != 4 && v != 8)
- return 0;
- *r = v;
- return 1;
+ int v;
+
+ if (exprop(n) != Omul)
+ return 0;
+ if (exprop(n->expr.args[1]) != Olit)
+ return 0;
+ if (n->expr.args[1]->expr.args[0]->type != Nlit)
+ return 0;
+ if (n->expr.args[1]->expr.args[0]->lit.littype != Lint)
+ return 0;
+ v = n->expr.args[1]->expr.args[0]->lit.intval;
+ if (v != 2 && v != 4 && v != 8)
+ return 0;
+ *r = v;
+ return 1;
}
static Loc *memloc(Isel *s, Node *e, Mode m)
{
- Node **args;
- Loc *l, *b, *o; /* location, base, offset */
- int scale;
-
- scale = 1;
- l = NULL;
- args = e->expr.args;
- if (exprop(e) == Oadd) {
- b = selexpr(s, args[0]);
- if (ismergablemul(args[1], &scale))
- o = selexpr(s, args[1]->expr.args[0]);
- else
- o = selexpr(s, args[1]);
-
- if (b->type != Locreg)
- b = inr(s, b);
- if (o->type == Loclit) {
- l = locmem(scale*o->lit, b, NULL, m);
- } else {
- b = inr(s, b);
- o = inr(s, o);
- l = locmems(0, b, o, scale, m);
- }
- } else {
- l = selexpr(s, e);
- l = inr(s, l);
- l = locmem(0, l, NULL, m);
- }
- assert(l != NULL);
- return l;
+ Node **args;
+ Loc *l, *b, *o; /* location, base, offset */
+ int scale;
+
+ scale = 1;
+ l = NULL;
+ args = e->expr.args;
+ if (exprop(e) == Oadd) {
+ b = selexpr(s, args[0]);
+ if (ismergablemul(args[1], &scale))
+ o = selexpr(s, args[1]->expr.args[0]);
+ else
+ o = selexpr(s, args[1]);
+
+ if (b->type != Locreg)
+ b = inr(s, b);
+ if (o->type == Loclit) {
+ l = locmem(scale*o->lit, b, NULL, m);
+ } else {
+ b = inr(s, b);
+ o = inr(s, o);
+ l = locmems(0, b, o, scale, m);
+ }
+ } else {
+ l = selexpr(s, e);
+ l = inr(s, l);
+ l = locmem(0, l, NULL, m);
+ }
+ assert(l != NULL);
+ return l;
}
static const Mode szmodes[] = {
- [8] = ModeQ,
- [4] = ModeL,
- [2] = ModeW,
- [1] = ModeB
+ [8] = ModeQ,
+ [4] = ModeL,
+ [2] = ModeW,
+ [1] = ModeB
};
static void blit(Isel *s, Loc *to, Loc *from, size_t dstoff, size_t srcoff, size_t sz, size_t align)
{
- size_t i, modesz;
- Loc *sp, *dp, *len; /* pointers to src, dst */
- Loc *tmp, *src, *dst; /* source memory, dst memory */
-
- assert(szmodes[align] != ModeNone); /* make sure we have a valid alignment */
- sp = inr(s, from);
- dp = inr(s, to);
-
- i = 0;
- if (align == 0)
- align = 8;
- if (sz <= 128) { /* arbitrary threshold; should be tuned */
- for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
- tmp = locreg(szmodes[modesz]);
- while (i + modesz <= sz) {
- src = locmem(i + srcoff, sp, NULL, szmodes[modesz]);
- dst = locmem(i + dstoff, dp, NULL, szmodes[modesz]);
- g(s, Imov, src, tmp, NULL);
- g(s, Imov, tmp, dst, NULL);
- i += modesz;
- }
- }
- } else {
- len = loclit(sz, ModeQ);
- sp = newr(s, from);
- dp = newr(s, to);
-
- /* length to blit */
- g(s, Imov, len, locphysreg(Rrcx), NULL);
- /* source address with offset */
- if (srcoff)
- g(s, Ilea, locmem(srcoff, sp, NULL, ModeQ), locphysreg(Rrsi), NULL);
- else
- g(s, Imov, sp, locphysreg(Rrsi), NULL);
- /* dest address with offset */
- if (dstoff)
- g(s, Ilea, locmem(dstoff, dp, NULL, ModeQ), locphysreg(Rrdi), NULL);
- else
- g(s, Imov, dp, locphysreg(Rrdi), NULL);
- g(s, Irepmovsb, NULL);
- }
-
+ size_t i, modesz;
+ Loc *sp, *dp, *len; /* pointers to src, dst */
+ Loc *tmp, *src, *dst; /* source memory, dst memory */
+
+ assert(szmodes[align] != ModeNone); /* make sure we have a valid alignment */
+ sp = inr(s, from);
+ dp = inr(s, to);
+
+ i = 0;
+ if (align == 0)
+ align = 8;
+ if (sz <= 128) { /* arbitrary threshold; should be tuned */
+ for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
+ tmp = locreg(szmodes[modesz]);
+ while (i + modesz <= sz) {
+ src = locmem(i + srcoff, sp, NULL, szmodes[modesz]);
+ dst = locmem(i + dstoff, dp, NULL, szmodes[modesz]);
+ g(s, Imov, src, tmp, NULL);
+ g(s, Imov, tmp, dst, NULL);
+ i += modesz;
+ }
+ }
+ } else {
+ len = loclit(sz, ModeQ);
+ sp = newr(s, from);
+ dp = newr(s, to);
+
+ /* length to blit */
+ g(s, Imov, len, locphysreg(Rrcx), NULL);
+ /* source address with offset */
+ if (srcoff)
+ g(s, Ilea, locmem(srcoff, sp, NULL, ModeQ), locphysreg(Rrsi), NULL);
+ else
+ g(s, Imov, sp, locphysreg(Rrsi), NULL);
+ /* dest address with offset */
+ if (dstoff)
+ g(s, Ilea, locmem(dstoff, dp, NULL, ModeQ), locphysreg(Rrdi), NULL);
+ else
+ g(s, Imov, dp, locphysreg(Rrdi), NULL);
+ g(s, Irepmovsb, NULL);
+ }
+
}
static void clear(Isel *s, Loc *val, size_t sz, size_t align)
{
- Loc *dp, *len, *rax; /* pointers to src, dst */
- Loc *zero, *dst; /* source memory, dst memory */
- size_t modesz, i;
-
- i = 0;
- dp = inr(s, val);
- rax = locphysreg(Rrax);
- g(s, Ixor, rax, rax, NULL);
- if (align == 0)
- align = 8;
- if (sz <= 128) { /* arbitrary threshold; should be tuned */
- for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
- zero = loclit(0, szmodes[modesz]);
- while (i + modesz <= sz) {
- zero = coreg(Rrax, szmodes[modesz]);
- dst = locmem(i, dp, NULL, szmodes[modesz]);
- g(s, Imov, zero, dst, NULL);
- i += modesz;
- }
- }
- } else {
- len = loclit(sz, ModeQ);
- /* length to blit */
- g(s, Imov, len, locphysreg(Rrcx), NULL);
- g(s, Imov, dp, locphysreg(Rrdi), NULL);
- g(s, Irepstosb, NULL);
- }
+ Loc *dp, *len, *rax; /* pointers to src, dst */
+ Loc *zero, *dst; /* source memory, dst memory */
+ size_t modesz, i;
+
+ i = 0;
+ dp = inr(s, val);
+ rax = locphysreg(Rrax);
+ g(s, Ixor, rax, rax, NULL);
+ if (align == 0)
+ align = 8;
+ if (sz <= 128) { /* arbitrary threshold; should be tuned */
+ for (modesz = align; szmodes[modesz] != ModeNone; modesz /= 2) {
+ zero = loclit(0, szmodes[modesz]);
+ while (i + modesz <= sz) {
+ zero = coreg(Rrax, szmodes[modesz]);
+ dst = locmem(i, dp, NULL, szmodes[modesz]);
+ g(s, Imov, zero, dst, NULL);
+ i += modesz;
+ }
+ }
+ } else {
+ len = loclit(sz, ModeQ);
+ /* length to blit */
+ g(s, Imov, len, locphysreg(Rrcx), NULL);
+ g(s, Imov, dp, locphysreg(Rrdi), NULL);
+ g(s, Irepstosb, NULL);
+ }
}
static void call(Isel *s, Node *n)
{
- AsmOp op;
- Node *fn;
- Loc *f, *e;
-
- if (exprop(n) == Ocall) {
- op = Icall;
- fn = n->expr.args[0];
- assert(tybase(exprtype(fn))->type == Tycode);
- f = locmeml(htget(s->globls, fn), NULL, NULL, mode(fn));
- } else {
- op = Icallind;
- f = selexpr(s, n->expr.args[0]);
- e = selexpr(s, n->expr.args[1]);
- g(s, Imov, e, locphysreg(Rrax), NULL);
- }
- g(s, op, f, NULL);
+ AsmOp op;
+ Node *fn;
+ Loc *f, *e;
+
+ if (exprop(n) == Ocall) {
+ op = Icall;
+ fn = n->expr.args[0];
+ assert(tybase(exprtype(fn))->type == Tycode);
+ f = locmeml(htget(s->globls, fn), NULL, NULL, mode(fn));
+ } else {
+ op = Icallind;
+ f = selexpr(s, n->expr.args[0]);
+ e = selexpr(s, n->expr.args[1]);
+ g(s, Imov, e, locphysreg(Rrax), NULL);
+ }
+ g(s, op, f, NULL);
}
static size_t countargs(Type *t)
{
- size_t nargs;
-
- t = tybase(t);
- nargs = t->nsub - 1;
- if (isstacktype(t->sub[0]))
- nargs++;
- /* valists are replaced with hidden type parameter,
- * which we want on the stack for ease of ABI */
- if (tybase(t->sub[t->nsub - 1])->type == Tyvalist)
- nargs--;
- return nargs;
+ size_t nargs;
+
+ t = tybase(t);
+ nargs = t->nsub - 1;
+ if (isstacktype(t->sub[0]))
+ nargs++;
+ /* valists are replaced with hidden type parameter,
+ * which we want on the stack for ease of ABI */
+ if (tybase(t->sub[t->nsub - 1])->type == Tyvalist)
+ nargs--;
+ return nargs;
}
static Loc *gencall(Isel *s, Node *n)
{
- Loc *src, *dst, *arg; /* values we reduced */
- size_t argsz, argoff, nargs, vasplit;
- size_t nfloats, nints;
- Loc *retloc, *rsp, *ret; /* hard-coded registers */
- Loc *stkbump; /* calculated stack offset */
- Type *t, *fn;
- Node **args;
- size_t i, a;
- int vararg;
-
- rsp = locphysreg(Rrsp);
- t = exprtype(n);
- if (tybase(t)->type == Tyvoid || isstacktype(t)) {
- retloc = NULL;
- ret = NULL;
- } else if (istyfloat(t)) {
- retloc = coreg(Rxmm0d, mode(n));
- ret = locreg(mode(n));
- } else {
- retloc = coreg(Rrax, mode(n));
- ret = locreg(mode(n));
- }
- fn = tybase(exprtype(n->expr.args[0]));
- /* calculate the number of args we expect to see, adjust
- * for a hidden return argument. */
- vasplit = countargs(fn);
- argsz = 0;
- if (exprop(n) == Ocall) {
- args = &n->expr.args[1];
- nargs = n->expr.nargs - 1;
- } else {
- args = &n->expr.args[2];
- nargs = n->expr.nargs - 2;
- }
- /* Have to calculate the amount to bump the stack
- * pointer by in one pass first, otherwise if we push
- * one at a time, we evaluate the args in reverse order.
- * Not good.
- *
- * Skip the first operand, since it's the function itself */
- for (i = 0; i < nargs; i++) {
- argsz = align(argsz, min(size(args[i]), Ptrsz));
- argsz += size(args[i]);
- }
- argsz = align(argsz, 16);
- stkbump = loclit(argsz, ModeQ);
- if (argsz)
- g(s, Isub, stkbump, rsp, NULL);
-
- /* Now, we can evaluate the arguments */
- argoff = 0;
- nfloats = 0;
- nints = 0;
- vararg = 0;
- for (i = 0; i < nargs; i++) {
- arg = selexpr(s, args[i]);
- argoff = alignto(argoff, exprtype(args[i]));
- if (i >= vasplit)
- vararg = 1;
- if (stacknode(args[i])) {
- src = locreg(ModeQ);
- g(s, Ilea, arg, src, NULL);
- a = tyalign(exprtype(args[i]));
- blit(s, rsp, src, argoff, 0, size(args[i]), a);
- argoff += size(args[i]);
- } else if (!vararg && isfloatmode(arg->mode) && nfloats < Nfloatregargs) {
- dst = coreg(floatargregs[nfloats], arg->mode);
- arg = inri(s, arg);
- g(s, Imovs, arg, dst, NULL);
- nfloats++;
- } else if (!vararg && isintmode(arg->mode) && nints < Nintregargs) {
- dst = coreg(intargregs[nints], arg->mode);
- arg = inri(s, arg);
- g(s, Imov, arg, dst, NULL);
- nints++;
- } else {
- dst = locmem(argoff, rsp, NULL, arg->mode);
- arg = inri(s, arg);
- stor(s, arg, dst);
- argoff += size(args[i]);
- }
- }
- call(s, n);
- if (argsz)
- g(s, Iadd, stkbump, rsp, NULL);
- if (retloc) {
- if (isfloatmode(retloc->mode))
- g(s, Imovs, retloc, ret, NULL);
- else
- g(s, Imov, retloc, ret, NULL);
- }
- return ret;
+ Loc *src, *dst, *arg; /* values we reduced */
+ size_t argsz, argoff, nargs, vasplit;
+ size_t nfloats, nints;
+ Loc *retloc, *rsp, *ret; /* hard-coded registers */
+ Loc *stkbump; /* calculated stack offset */
+ Type *t, *fn;
+ Node **args;
+ size_t i, a;
+ int vararg;
+
+ rsp = locphysreg(Rrsp);
+ t = exprtype(n);
+ if (tybase(t)->type == Tyvoid || isstacktype(t)) {
+ retloc = NULL;
+ ret = NULL;
+ } else if (istyfloat(t)) {
+ retloc = coreg(Rxmm0d, mode(n));
+ ret = locreg(mode(n));
+ } else {
+ retloc = coreg(Rrax, mode(n));
+ ret = locreg(mode(n));
+ }
+ fn = tybase(exprtype(n->expr.args[0]));
+ /* calculate the number of args we expect to see, adjust
+ * for a hidden return argument. */
+ vasplit = countargs(fn);
+ argsz = 0;
+ if (exprop(n) == Ocall) {
+ args = &n->expr.args[1];
+ nargs = n->expr.nargs - 1;
+ } else {
+ args = &n->expr.args[2];
+ nargs = n->expr.nargs - 2;
+ }
+ /* Have to calculate the amount to bump the stack
+ * pointer by in one pass first, otherwise if we push
+ * one at a time, we evaluate the args in reverse order.
+ * Not good.
+ *
+ * Skip the first operand, since it's the function itself */
+ for (i = 0; i < nargs; i++) {
+ argsz = align(argsz, min(size(args[i]), Ptrsz));
+ argsz += size(args[i]);
+ }
+ argsz = align(argsz, 16);
+ stkbump = loclit(argsz, ModeQ);
+ if (argsz)
+ g(s, Isub, stkbump, rsp, NULL);
+
+ /* Now, we can evaluate the arguments */
+ argoff = 0;
+ nfloats = 0;
+ nints = 0;
+ vararg = 0;
+ for (i = 0; i < nargs; i++) {
+ arg = selexpr(s, args[i]);
+ argoff = alignto(argoff, exprtype(args[i]));
+ if (i >= vasplit)
+ vararg = 1;
+ if (stacknode(args[i])) {
+ src = locreg(ModeQ);
+ g(s, Ilea, arg, src, NULL);
+ a = tyalign(exprtype(args[i]));
+ blit(s, rsp, src, argoff, 0, size(args[i]), a);
+ argoff += size(args[i]);
+ } else if (!vararg && isfloatmode(arg->mode) && nfloats < Nfloatregargs) {
+ dst = coreg(floatargregs[nfloats], arg->mode);
+ arg = inri(s, arg);
+ g(s, Imovs, arg, dst, NULL);
+ nfloats++;
+ } else if (!vararg && isintmode(arg->mode) && nints < Nintregargs) {
+ dst = coreg(intargregs[nints], arg->mode);
+ arg = inri(s, arg);
+ g(s, Imov, arg, dst, NULL);
+ nints++;
+ } else {
+ dst = locmem(argoff, rsp, NULL, arg->mode);
+ arg = inri(s, arg);
+ stor(s, arg, dst);
+ argoff += size(args[i]);
+ }
+ }
+ call(s, n);
+ if (argsz)
+ g(s, Iadd, stkbump, rsp, NULL);
+ if (retloc) {
+ if (isfloatmode(retloc->mode))
+ g(s, Imovs, retloc, ret, NULL);
+ else
+ g(s, Imov, retloc, ret, NULL);
+ }
+ return ret;
}
Loc *selexpr(Isel *s, Node *n)
{
- Loc *a, *b, *c, *d, *r;
- Loc *edx, *cl; /* x86 wants some hard-coded regs */
- Node **args;
- size_t al;
- Op op;
-
- args = n->expr.args;
- edx = locphysreg(Redx);
- cl = locphysreg(Rcl);
- r = NULL;
- switch (exprop(n)) {
- case Oadd: r = binop(s, Iadd, args[0], args[1]); break;
- case Osub: r = binop(s, Isub, args[0], args[1]); break;
- case Obor: r = binop(s, Ior, args[0], args[1]); break;
- case Oband: r = binop(s, Iand, args[0], args[1]); break;
- case Obxor: r = binop(s, Ixor, args[0], args[1]); break;
- case Omul:
- if (size(args[0]) == 1) {
- a = selexpr(s, args[0]);
- b = inr(s, selexpr(s, args[1]));
-
- c = locphysreg(Ral);
- r = locreg(a->mode);
- g(s, Imov, a, c, NULL);
- g(s, Iimul_r, b, NULL);
- g(s, Imov, c, r, NULL);
- } else {
- r = binop(s, Iimul, args[0], args[1]);
- }
- break;
- case Odiv:
- case Omod:
- /* these get clobbered by the div insn */
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- b = newr(s, b);
- c = coreg(Reax, mode(n));
- r = locreg(a->mode);
- g(s, Imov, a, c, NULL);
- if (istysigned(exprtype(args[0]))) {
- switch (r->mode) {
- case ModeB: g(s, Imovsx, c, coreg(Rrax, ModeW), NULL); break;
- case ModeW: g(s, Icwd, NULL); break;
- case ModeL: g(s, Icdq, NULL); break;
- case ModeQ: g(s, Icqo, NULL); break;
- default: die("invalid mode in division"); break;
- }
- g(s, Iidiv, b, NULL);
- } else {
- if (r->mode == ModeB)
- g(s, Ixor, locphysreg(Rah), locphysreg(Rah), NULL);
- else
- g(s, Ixor, edx, edx, NULL);
- g(s, Idiv, b, NULL);
- }
- if (exprop(n) == Odiv)
- d = coreg(Reax, mode(n));
- else if (r->mode != ModeB)
- d = coreg(Redx, mode(n));
- else
- d = locphysreg(Rah);
- g(s, Imov, d, r, NULL);
- break;
- case Oneg:
- r = selexpr(s, args[0]);
- r = newr(s, r);
- g(s, Ineg, r, NULL);
- break;
-
- /* fp expressions */
- case Ofadd: r = binop(s, Iadds, args[0], args[1]); break;
- case Ofsub: r = binop(s, Isubs, args[0], args[1]); break;
- case Ofmul: r = binop(s, Imuls, args[0], args[1]); break;
- case Ofdiv: r = binop(s, Idivs, args[0], args[1]); break;
- case Ofneg:
- r = selexpr(s, args[0]);
- r = newr(s, r);
- a = NULL;
- b = NULL;
- if (mode(args[0]) == ModeF) {
- a = locreg(ModeF);
- b = loclit(1LL << (31), ModeF);
- g(s, Imovs, r, a);
- } else if (mode(args[0]) == ModeD) {
- a = locreg(ModeQ);
- b = loclit(1LL << 63, ModeQ);
- g(s, Imov, r, a, NULL);
- }
- g(s, Ixor, b, a, NULL);
- g(s, Imov, a, r, NULL);
- break;
- case Obsl:
- case Obsr:
- a = newr(s, selexpr(s, args[0]));
- b = selexpr(s, args[1]);
- if (b->type == Loclit) {
- d = b;
- } else {
- c = coreg(Rcl, b->mode);
- g(s, Imov, b, c, NULL);
- d = cl;
- }
- if (exprop(n) == Obsr) {
- if (istysigned(n->expr.type))
- g(s, Isar, d, a, NULL);
- else
- g(s, Ishr, d, a, NULL);
- } else {
- g(s, Ishl, d, a, NULL);
- }
- r = a;
- break;
- case Obnot:
- r = selexpr(s, args[0]);
- r = newr(s, r);
- g(s, Inot, r, NULL);
- break;
-
- case Oderef:
- r = memloc(s, args[0], mode(n));
- break;
-
- case Oaddr:
- a = selexpr(s, args[0]);
- if (a->type == Loclbl || (a->type == Locmeml && !a->mem.base)) {
- r = loclitl(a->lbl);
- } else {
- r = locreg(ModeQ);
- g(s, Ilea, a, r, NULL);
- }
- break;
-
- case Olnot:
- a = newr(s, selexpr(s, args[0]));
- b = locreg(ModeB);
- r = locreg(mode(n));
- /* lnot only valid for integer-like values */
- g(s, reloptab[exprop(n)].test, a, a, NULL);
- g(s, reloptab[exprop(n)].getflag, b, NULL);
- movz(s, b, r);
- break;
-
- case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
- case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
- case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- a = newr(s, a);
- c = locreg(ModeB);
- r = locreg(mode(n));
- g(s, reloptab[exprop(n)].test, b, a, NULL);
- g(s, reloptab[exprop(n)].getflag, c, NULL);
- movz(s, c, r);
- return r;
-
- case Oasn: /* relabel */
- die("Unimplemented op %s", opstr[exprop(n)]);
- break;
- case Oset:
- op = exprop(args[0]);
- assert(op == Ovar || op == Oderef || op == Ogap);
- assert(!stacknode(args[0]));
-
- if (op == Ogap)
- break;
-
- b = selexpr(s, args[1]);
- if (exprop(args[0]) == Oderef)
- a = memloc(s, args[0]->expr.args[0], mode(n));
- else
- a = selexpr(s, args[0]);
- b = inri(s, b);
- if (isfloatmode(b->mode))
- g(s, Imovs, b, a, NULL);
- else
- g(s, Imov, b, a, NULL);
- r = b;
- break;
- case Ocall:
- case Ocallind:
- r = gencall(s, n);
- break;
- case Oret:
- a = locstrlbl(s->cfg->end->lbls[0]);
- g(s, Ijmp, a, NULL);
- break;
- case Ojmp:
- g(s, Ijmp, loclbl(args[0]), NULL);
- break;
- case Ocjmp:
- selcjmp(s, n, args);
- break;
- case Ovjmp:
- selvjmp(s, n, args);
- break;
- case Olit: /* fall through */
- r = loc(s, n);
- break;
- case Ovar:
- if (isconstfn(n)) {
- r = locreg(ModeQ);
- a = loc(s, n);
- g(s, Ilea, a, r, NULL);
- } else {
- r = loc(s, n);
- }
- break;
- case Ogap:
- break;
- case Oblit:
- a = selexpr(s, args[0]);
- r = selexpr(s, args[1]);
- al = alignto(1, args[0]->expr.type->sub[0]);
- blit(s, a, r, 0, 0, args[2]->expr.args[0]->lit.intval, al);
- break;
-
- case Oclear:
- a = selexpr(s, args[0]);
- clear(s, a, args[1]->expr.args[0]->lit.intval, 0);
- break;
-
- /* cast operators that actually modify the values */
- case Otrunc:
- a = selexpr(s, args[0]);
- a = inr(s, a);
- r = locreg(mode(n));
- g(s, Imov, a, r, NULL);
- break;
- case Ozwiden:
- a = selexpr(s, args[0]);
- a = inr(s, a);
- r = locreg(mode(n));
- movz(s, a, r);
- break;
- case Oswiden:
- a = selexpr(s, args[0]);
- a = inr(s, a);
- r = locreg(mode(n));
- g(s, Imovsx, a, r, NULL);
- break;
- case Oint2flt:
- a = selexpr(s, args[0]);
- r = locreg(mode(n));
- g(s, Icvttsi2sd, a, r, NULL);
- break;
- case Oflt2int:
- a = selexpr(s, args[0]);
- r = locreg(mode(n));
- g(s, Icvttsd2si, a, r, NULL);
- break;
-
- case Oflt2flt:
- a = selexpr(s, args[0]);
- r = locreg(mode(n));
- if (a->mode == ModeD)
- g(s, Icvttsd2ss, a, r, NULL);
- else
- g(s, Icvttss2sd, a, r, NULL);
- break;
- case Odead:
- case Oundef:
- case Odef:
- /* nothing */
- break;
-
- /* These operators should never show up in the reduced trees,
- * since they should have been replaced with more primitive
- * expressions by now */
- case Obad: case Opreinc: case Opostinc: case Opredec:
- case Opostdec: case Olor: case Oland: case Oaddeq:
- case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
- case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
- case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
- case Oucon: case Otup: case Oarr: case Ostruct:
- case Oslice: case Oidx: case Osize: case Otupget: case Oidxlen:
- case Obreak: case Ocontinue:
- case Numops:
- dump(n, stdout);
- die("Should not see %s in isel", opstr[exprop(n)]);
- break;
- }
- return r;
+ Loc *a, *b, *c, *d, *r;
+ Loc *edx, *cl; /* x86 wants some hard-coded regs */
+ Node **args;
+ size_t al;
+ Op op;
+
+ args = n->expr.args;
+ edx = locphysreg(Redx);
+ cl = locphysreg(Rcl);
+ r = NULL;
+ switch (exprop(n)) {
+ case Oadd: r = binop(s, Iadd, args[0], args[1]); break;
+ case Osub: r = binop(s, Isub, args[0], args[1]); break;
+ case Obor: r = binop(s, Ior, args[0], args[1]); break;
+ case Oband: r = binop(s, Iand, args[0], args[1]); break;
+ case Obxor: r = binop(s, Ixor, args[0], args[1]); break;
+ case Omul:
+ if (size(args[0]) == 1) {
+ a = selexpr(s, args[0]);
+ b = inr(s, selexpr(s, args[1]));
+
+ c = locphysreg(Ral);
+ r = locreg(a->mode);
+ g(s, Imov, a, c, NULL);
+ g(s, Iimul_r, b, NULL);
+ g(s, Imov, c, r, NULL);
+ } else {
+ r = binop(s, Iimul, args[0], args[1]);
+ }
+ break;
+ case Odiv:
+ case Omod:
+ /* these get clobbered by the div insn */
+ a = selexpr(s, args[0]);
+ b = selexpr(s, args[1]);
+ b = newr(s, b);
+ c = coreg(Reax, mode(n));
+ r = locreg(a->mode);
+ g(s, Imov, a, c, NULL);
+ if (istysigned(exprtype(args[0]))) {
+ switch (r->mode) {
+ case ModeB: g(s, Imovsx, c, coreg(Rrax, ModeW), NULL); break;
+ case ModeW: g(s, Icwd, NULL); break;
+ case ModeL: g(s, Icdq, NULL); break;
+ case ModeQ: g(s, Icqo, NULL); break;
+ default: die("invalid mode in division"); break;
+ }
+ g(s, Iidiv, b, NULL);
+ } else {
+ if (r->mode == ModeB)
+ g(s, Ixor, locphysreg(Rah), locphysreg(Rah), NULL);
+ else
+ g(s, Ixor, edx, edx, NULL);
+ g(s, Idiv, b, NULL);
+ }
+ if (exprop(n) == Odiv)
+ d = coreg(Reax, mode(n));
+ else if (r->mode != ModeB)
+ d = coreg(Redx, mode(n));
+ else
+ d = locphysreg(Rah);
+ g(s, Imov, d, r, NULL);
+ break;
+ case Oneg:
+ r = selexpr(s, args[0]);
+ r = newr(s, r);
+ g(s, Ineg, r, NULL);
+ break;
+
+ /* fp expressions */
+ case Ofadd: r = binop(s, Iadds, args[0], args[1]); break;
+ case Ofsub: r = binop(s, Isubs, args[0], args[1]); break;
+ case Ofmul: r = binop(s, Imuls, args[0], args[1]); break;
+ case Ofdiv: r = binop(s, Idivs, args[0], args[1]); break;
+ case Ofneg:
+ r = selexpr(s, args[0]);
+ r = newr(s, r);
+ a = NULL;
+ b = NULL;
+ if (mode(args[0]) == ModeF) {
+ a = locreg(ModeF);
+ b = loclit(1LL << (31), ModeF);
+ g(s, Imovs, r, a);
+ } else if (mode(args[0]) == ModeD) {
+ a = locreg(ModeQ);
+ b = loclit(1LL << 63, ModeQ);
+ g(s, Imov, r, a, NULL);
+ }
+ g(s, Ixor, b, a, NULL);
+ g(s, Imov, a, r, NULL);
+ break;
+ case Obsl:
+ case Obsr:
+ a = newr(s, selexpr(s, args[0]));
+ b = selexpr(s, args[1]);
+ if (b->type == Loclit) {
+ d = b;
+ } else {
+ c = coreg(Rcl, b->mode);
+ g(s, Imov, b, c, NULL);
+ d = cl;
+ }
+ if (exprop(n) == Obsr) {
+ if (istysigned(n->expr.type))
+ g(s, Isar, d, a, NULL);
+ else
+ g(s, Ishr, d, a, NULL);
+ } else {
+ g(s, Ishl, d, a, NULL);
+ }
+ r = a;
+ break;
+ case Obnot:
+ r = selexpr(s, args[0]);
+ r = newr(s, r);
+ g(s, Inot, r, NULL);
+ break;
+
+ case Oderef:
+ r = memloc(s, args[0], mode(n));
+ break;
+
+ case Oaddr:
+ a = selexpr(s, args[0]);
+ if (a->type == Loclbl || (a->type == Locmeml && !a->mem.base)) {
+ r = loclitl(a->lbl);
+ } else {
+ r = locreg(ModeQ);
+ g(s, Ilea, a, r, NULL);
+ }
+ break;
+
+ case Olnot:
+ a = newr(s, selexpr(s, args[0]));
+ b = locreg(ModeB);
+ r = locreg(mode(n));
+ /* lnot only valid for integer-like values */
+ g(s, reloptab[exprop(n)].test, a, a, NULL);
+ g(s, reloptab[exprop(n)].getflag, b, NULL);
+ movz(s, b, r);
+ break;
+
+ case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
+ case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
+ case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
+ a = selexpr(s, args[0]);
+ b = selexpr(s, args[1]);
+ a = newr(s, a);
+ c = locreg(ModeB);
+ r = locreg(mode(n));
+ g(s, reloptab[exprop(n)].test, b, a, NULL);
+ g(s, reloptab[exprop(n)].getflag, c, NULL);
+ movz(s, c, r);
+ return r;
+
+ case Oasn: /* relabel */
+ die("Unimplemented op %s", opstr[exprop(n)]);
+ break;
+ case Oset:
+ op = exprop(args[0]);
+ assert(op == Ovar || op == Oderef || op == Ogap);
+ assert(!stacknode(args[0]));
+
+ if (op == Ogap)
+ break;
+
+ b = selexpr(s, args[1]);
+ if (exprop(args[0]) == Oderef)
+ a = memloc(s, args[0]->expr.args[0], mode(n));
+ else
+ a = selexpr(s, args[0]);
+ b = inri(s, b);
+ if (isfloatmode(b->mode))
+ g(s, Imovs, b, a, NULL);
+ else
+ g(s, Imov, b, a, NULL);
+ r = b;
+ break;
+ case Ocall:
+ case Ocallind:
+ r = gencall(s, n);
+ break;
+ case Oret:
+ a = locstrlbl(s->cfg->end->lbls[0]);
+ g(s, Ijmp, a, NULL);
+ break;
+ case Ojmp:
+ g(s, Ijmp, loclbl(args[0]), NULL);
+ break;
+ case Ocjmp:
+ selcjmp(s, n, args);
+ break;
+ case Ovjmp:
+ selvjmp(s, n, args);
+ break;
+ case Olit: /* fall through */
+ r = loc(s, n);
+ break;
+ case Ovar:
+ if (isconstfn(n)) {
+ r = locreg(ModeQ);
+ a = loc(s, n);
+ g(s, Ilea, a, r, NULL);
+ } else {
+ r = loc(s, n);
+ }
+ break;
+ case Ogap:
+ break;
+ case Oblit:
+ a = selexpr(s, args[0]);
+ r = selexpr(s, args[1]);
+ al = alignto(1, args[0]->expr.type->sub[0]);
+ blit(s, a, r, 0, 0, args[2]->expr.args[0]->lit.intval, al);
+ break;
+
+ case Oclear:
+ a = selexpr(s, args[0]);
+ clear(s, a, args[1]->expr.args[0]->lit.intval, 0);
+ break;
+
+ /* cast operators that actually modify the values */
+ case Otrunc:
+ a = selexpr(s, args[0]);
+ a = inr(s, a);
+ r = locreg(mode(n));
+ g(s, Imov, a, r, NULL);
+ break;
+ case Ozwiden:
+ a = selexpr(s, args[0]);
+ a = inr(s, a);
+ r = locreg(mode(n));
+ movz(s, a, r);
+ break;
+ case Oswiden:
+ a = selexpr(s, args[0]);
+ a = inr(s, a);
+ r = locreg(mode(n));
+ g(s, Imovsx, a, r, NULL);
+ break;
+ case Oint2flt:
+ a = selexpr(s, args[0]);
+ r = locreg(mode(n));
+ g(s, Icvttsi2sd, a, r, NULL);
+ break;
+ case Oflt2int:
+ a = selexpr(s, args[0]);
+ r = locreg(mode(n));
+ g(s, Icvttsd2si, a, r, NULL);
+ break;
+
+ case Oflt2flt:
+ a = selexpr(s, args[0]);
+ r = locreg(mode(n));
+ if (a->mode == ModeD)
+ g(s, Icvttsd2ss, a, r, NULL);
+ else
+ g(s, Icvttss2sd, a, r, NULL);
+ break;
+ case Odead:
+ case Oundef:
+ case Odef:
+ /* nothing */
+ break;
+
+ /* These operators should never show up in the reduced trees,
+ * since they should have been replaced with more primitive
+ * expressions by now */
+ case Obad: case Opreinc: case Opostinc: case Opredec:
+ case Opostdec: case Olor: case Oland: case Oaddeq:
+ case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
+ case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
+ case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
+ case Oucon: case Otup: case Oarr: case Ostruct:
+ case Oslice: case Oidx: case Osize: case Otupget: case Oidxlen:
+ case Obreak: case Ocontinue:
+ case Numops:
+ dump(n, stdout);
+ die("Should not see %s in isel", opstr[exprop(n)]);
+ break;
+ }
+ return r;
}
static void isel(Isel *s, Node *n)
{
- switch (n->type) {
- case Nexpr:
- selexpr(s, n);
- break;
- case Ndecl:
- break;
- default:
- die("Bad node type in isel()");
- break;
- }
+ switch (n->type) {
+ case Nexpr:
+ selexpr(s, n);
+ break;
+ case Ndecl:
+ break;
+ default:
+ die("Bad node type in isel()");
+ break;
+ }
}
/* %rax is for int returns, %xmm0d is for floating returns */
Reg savedregs[] = {
- Rr12, Rr13, Rr14, Rr15,
- Rnone
+ Rr12, Rr13, Rr14, Rr15,
+ Rnone
};
void addarglocs(Isel *s, Func *fn)
{
- size_t i, nints, nfloats, nargs;
- size_t argoff;
- int vararg;
- Node *arg;
- Loc *a, *l;
-
- argoff = 0;
- nfloats = 0;
- nints = 0;
- vararg = 0;
- nargs = countargs(fn->type);
- for (i = 0; i < fn->nargs; i++) {
- arg = fn->args[i];
- argoff = align(argoff, min(size(arg), Ptrsz));
- if (i >= nargs)
- vararg = 1;
- if (stacknode(arg)) {
- htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
- argoff += size(arg);
- } else if (!vararg && isfloatmode(mode(arg)) && nfloats < Nfloatregargs) {
- a = coreg(floatargregs[nfloats], mode(arg));
- l = loc(s, arg);
- g(s, Imovs, a, l, NULL);
- htput(s->reglocs, arg, l);
- nfloats++;
- } else if (!vararg && isintmode(mode(arg)) && nints < Nintregargs) {
- a = coreg(intargregs[nints], mode(arg));
- l = loc(s, arg);
- g(s, Imov, a, l, NULL);
- htput(s->reglocs, arg, l);
- nints++;
- } else {
- htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
- argoff += size(arg);
- }
- }
+ size_t i, nints, nfloats, nargs;
+ size_t argoff;
+ int vararg;
+ Node *arg;
+ Loc *a, *l;
+
+ argoff = 0;
+ nfloats = 0;
+ nints = 0;
+ vararg = 0;
+ nargs = countargs(fn->type);
+ for (i = 0; i < fn->nargs; i++) {
+ arg = fn->args[i];
+ argoff = align(argoff, min(size(arg), Ptrsz));
+ if (i >= nargs)
+ vararg = 1;
+ if (stacknode(arg)) {
+ htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
+ argoff += size(arg);
+ } else if (!vararg && isfloatmode(mode(arg)) && nfloats < Nfloatregargs) {
+ a = coreg(floatargregs[nfloats], mode(arg));
+ l = loc(s, arg);
+ g(s, Imovs, a, l, NULL);
+ htput(s->reglocs, arg, l);
+ nfloats++;
+ } else if (!vararg && isintmode(mode(arg)) && nints < Nintregargs) {
+ a = coreg(intargregs[nints], mode(arg));
+ l = loc(s, arg);
+ g(s, Imov, a, l, NULL);
+ htput(s->reglocs, arg, l);
+ nints++;
+ } else {
+ htput(s->stkoff, arg, itop(-(argoff + 2*Ptrsz)));
+ argoff += size(arg);
+ }
+ }
}
static void prologue(Isel *s, Func *fn, size_t sz)
{
- Loc *rsp;
- Loc *rbp;
- Loc *stksz;
- Loc *phys;
- size_t i;
-
- rsp = locphysreg(Rrsp);
- rbp = locphysreg(Rrbp);
- stksz = loclit(sz, ModeQ);
- /* enter function */
- g(s, Ipush, rbp, NULL);
- g(s, Imov, rsp, rbp, NULL);
- g(s, Isub, stksz, rsp, NULL);
- /* save registers */
- for (i = 0; savedregs[i] != Rnone; i++) {
- phys = locphysreg(savedregs[i]);
- s->calleesave[i] = locreg(phys->mode);
- if (isfloatmode(phys->mode)) {
- g(s, Imovs, phys, s->calleesave[i], NULL);
- } else {
- g(s, Imov, phys, s->calleesave[i], NULL);
- }
- }
- if (s->envp)
- g(s, Imov, locphysreg(Rrax), s->envp, NULL);
- addarglocs(s, fn);
- s->nsaved = i;
- s->stksz = stksz; /* need to update if we spill */
+ Loc *rsp;
+ Loc *rbp;
+ Loc *stksz;
+ Loc *phys;
+ size_t i;
+
+ rsp = locphysreg(Rrsp);
+ rbp = locphysreg(Rrbp);
+ stksz = loclit(sz, ModeQ);
+ /* enter function */
+ g(s, Ipush, rbp, NULL);
+ g(s, Imov, rsp, rbp, NULL);
+ g(s, Isub, stksz, rsp, NULL);
+ /* save registers */
+ for (i = 0; savedregs[i] != Rnone; i++) {
+ phys = locphysreg(savedregs[i]);
+ s->calleesave[i] = locreg(phys->mode);
+ if (isfloatmode(phys->mode)) {
+ g(s, Imovs, phys, s->calleesave[i], NULL);
+ } else {
+ g(s, Imov, phys, s->calleesave[i], NULL);
+ }
+ }
+ if (s->envp)
+ g(s, Imov, locphysreg(Rrax), s->envp, NULL);
+ addarglocs(s, fn);
+ s->nsaved = i;
+ s->stksz = stksz; /* need to update if we spill */
}
static void epilogue(Isel *s)
{
- Loc *rsp, *rbp;
- Loc *ret;
- size_t i;
-
- rsp = locphysreg(Rrsp);
- rbp = locphysreg(Rrbp);
- if (s->ret) {
- ret = loc(s, s->ret);
- if (istyfloat(exprtype(s->ret)))
- g(s, Imovs, ret, coreg(Rxmm0d, ret->mode), NULL);
- else
- g(s, Imov, ret, coreg(Rax, ret->mode), NULL);
- }
- /* restore registers */
- for (i = 0; savedregs[i] != Rnone; i++) {
- if (isfloatmode(s->calleesave[i]->mode)) {
- g(s, Imovs, s->calleesave[i], locphysreg(savedregs[i]), NULL);
- } else {
- g(s, Imov, s->calleesave[i], locphysreg(savedregs[i]), NULL);
- }
- }
- /* leave function */
- g(s, Imov, rbp, rsp, NULL);
- g(s, Ipop, rbp, NULL);
- g(s, Iret, NULL);
+ Loc *rsp, *rbp;
+ Loc *ret;
+ size_t i;
+
+ rsp = locphysreg(Rrsp);
+ rbp = locphysreg(Rrbp);
+ if (s->ret) {
+ ret = loc(s, s->ret);
+ if (istyfloat(exprtype(s->ret)))
+ g(s, Imovs, ret, coreg(Rxmm0d, ret->mode), NULL);
+ else
+ g(s, Imov, ret, coreg(Rax, ret->mode), NULL);
+ }
+ /* restore registers */
+ for (i = 0; savedregs[i] != Rnone; i++) {
+ if (isfloatmode(s->calleesave[i]->mode)) {
+ g(s, Imovs, s->calleesave[i], locphysreg(savedregs[i]), NULL);
+ } else {
+ g(s, Imov, s->calleesave[i], locphysreg(savedregs[i]), NULL);
+ }
+ }
+ /* leave function */
+ g(s, Imov, rbp, rsp, NULL);
+ g(s, Ipop, rbp, NULL);
+ g(s, Iret, NULL);
}
static Asmbb *mkasmbb(Bb *bb)
{
- Asmbb *as;
-
- if (!bb)
- return NULL;
- as = zalloc(sizeof(Asmbb));
- as->id = bb->id;
- as->pred = bsdup(bb->pred);
- as->succ = bsdup(bb->succ);
- as->lbls = memdup(bb->lbls, bb->nlbls*sizeof(char*));
- as->nlbls = bb->nlbls;
- return as;
+ Asmbb *as;
+
+ if (!bb)
+ return NULL;
+ as = zalloc(sizeof(Asmbb));
+ as->id = bb->id;
+ as->pred = bsdup(bb->pred);
+ as->succ = bsdup(bb->succ);
+ as->lbls = memdup(bb->lbls, bb->nlbls*sizeof(char*));
+ as->nlbls = bb->nlbls;
+ return as;
}
void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab)
{
- Node *n;
- Bb *bb;
- size_t i, j;
- char buf[128];
-
-
- for (i = 0; i < fn->cfg->nbb; i++)
- lappend(&is->bb, &is->nbb, mkasmbb(fn->cfg->bb[i]));
-
- is->curbb = is->bb[0];
- prologue(is, fn, fn->stksz);
- for (j = 0; j < fn->cfg->nbb - 1; j++) {
- is->curbb = is->bb[j];
- if (!is->bb[j])
- continue;
- bb = fn->cfg->bb[j];
- for (i = 0; i < bb->nnl; i++) {
- /* put in a comment that says where this line comes from */
- n = bb->nl[i];
- bprintf(buf, sizeof buf, "bb = %ld, bbidx = %ld, %s:%d",
- j, i, file->file.files[n->loc.file], n->loc.line);
- g(is, Icomment, locstrlbl(buf), NULL);
- isel(is, fn->cfg->bb[j]->nl[i]);
- }
- }
- is->curbb = is->bb[is->nbb - 1];
- epilogue(is);
- peep(is);
- regalloc(is);
- is->stksz->lit = align(is->stksz->lit, 16);
+ Node *n;
+ Bb *bb;
+ size_t i, j;
+ char buf[128];
+
+
+ for (i = 0; i < fn->cfg->nbb; i++)
+ lappend(&is->bb, &is->nbb, mkasmbb(fn->cfg->bb[i]));
+
+ is->curbb = is->bb[0];
+ prologue(is, fn, fn->stksz);
+ for (j = 0; j < fn->cfg->nbb - 1; j++) {
+ is->curbb = is->bb[j];
+ if (!is->bb[j])
+ continue;
+ bb = fn->cfg->bb[j];
+ for (i = 0; i < bb->nnl; i++) {
+ /* put in a comment that says where this line comes from */
+ n = bb->nl[i];
+ bprintf(buf, sizeof buf, "bb = %ld, bbidx = %ld, %s:%d",
+ j, i, file->file.files[n->loc.file], n->loc.line);
+ g(is, Icomment, locstrlbl(buf), NULL);
+ isel(is, fn->cfg->bb[j]->nl[i]);
+ }
+ }
+ is->curbb = is->bb[is->nbb - 1];
+ epilogue(is);
+ peep(is);
+ regalloc(is);
+ is->stksz->lit = align(is->stksz->lit, 16);
}