ref: e96403b109bba4cf9581079a9bdf7dec22384075
parent: 53d4b23c3f4dc40f8f3d78343b35b12495193fcf
author: Ori Bernstein <[email protected]>
date: Thu Jun 7 12:05:53 EDT 2012
Add blit operator. For copying around structs/slices/anything that doesn't fit into a register.
--- a/8/isel.c
+++ b/8/isel.c
@@ -518,6 +518,34 @@
return eax;
}
+void blit(Isel *s, Loc a, Loc b, int sz)
+{
+ int i;
+ Reg sp, dp; /* pointers to src, dst */
+ Loc tmp, src, dst; /* source memory, dst memory */
+
+ sp = inr(s, a).reg;
+ dp = inr(s, b).reg;
+
+ /* Slightly funny loop condition: We might have trailing bytes
+ * that we can't blit word-wise. */
+ tmp = getreg(s, ModeL);
+ for (i = 0; i + 4 <= sz; i+= 4) {
+ locmem(&src, i, sp, Rnone, ModeL);
+ locmem(&dst, i, dp, Rnone, ModeL);
+ g(s, Imov, &src, &tmp, NULL);
+ g(s, Imov, &tmp, &dst, NULL);
+ }
+ /* now, the trailing bytes */
+ tmp = coreg(tmp, ModeB);
+ for (; i < sz; i++) {
+ locmem(&src, i, sp, Rnone, ModeB);
+ locmem(&dst, i, dp, Rnone, ModeB);
+ g(s, Imov, &src, &tmp, NULL);
+ g(s, Imov, &tmp, &dst, NULL);
+ }
+}
+
Loc selexpr(Isel *s, Node *n)
{
Loc a, b, c, r;
@@ -666,7 +694,12 @@
break;
case Olbl:
loclbl(&r, args[0]);
- break;
+ break;
+ case Oblit:
+ a = selexpr(s, args[0]);
+ b = selexpr(s, args[1]);
+ blit(s, a, b, args[2]->expr.args[0]->lit.intval);
+ break;
/* These operators should never show up in the reduced trees,
* since they should have been replaced with more primitive
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -414,31 +414,31 @@
t = lval(s, args[0]);
v = mkexpr(-1, Oadd, one, t, NULL);
r = mkexpr(-1, Ostor, t, v, NULL);
- lappend(&s->incqueue, &s->nqueue, t);
+ lappend(&s->incqueue, &s->nqueue, t);
break;
case Opredec:
t = lval(s, args[0]);
v = mkexpr(-1, Osub, one, t, NULL);
r = mkexpr(-1, Ostor, t, v, NULL);
- lappend(&s->incqueue, &s->nqueue, t);
+ lappend(&s->incqueue, &s->nqueue, t);
break;
/* expr(x++)
- * =>
+ * =>
* expr
- * x = x + 1
+ * x = x + 1
*/
case Opostinc:
r = lval(s, args[0]);
v = mkexpr(-1, Oadd, one, r, NULL);
t = mkexpr(-1, Ostor, r, v, NULL);
- lappend(&s->incqueue, &s->nqueue, t);
+ lappend(&s->incqueue, &s->nqueue, t);
break;
case Opostdec:
r = lval(s, args[0]);
v = mkexpr(-1, Osub, one, args[0], NULL);
t = mkexpr(-1, Ostor, r, v, NULL);
- lappend(&s->incqueue, &s->nqueue, t);
+ lappend(&s->incqueue, &s->nqueue, t);
break;
case Olit:
case Ovar:
@@ -457,8 +457,15 @@
break;
case Oasn:
t = lval(s, args[0]);
- v = rval(s, args[1]);
- r = mkexpr(-1, Ostor, t, v, NULL);
+ u = rval(s, args[1]);
+ if (size(n) > 4) {
+ t = mkexpr(-1, Oaddr, t, NULL);
+ u = mkexpr(-1, Oaddr, u, NULL);
+ v = mkexpr(-1, Olit, mkint(-1, size(n)), NULL);
+ r = mkexpr(-1, Oblit, t, u, v, NULL);
+ } else {
+ r = mkexpr(-1, Ostor, t, u, NULL);
+ }
break;
default:
for (i = 0; i < n->expr.nargs; i++)
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -374,9 +374,10 @@
break;
case Olbl: /* :lbl -> void* */
settype(n, mktyptr(n->line, mkty(-1, Tyvoid)));
- case Obad: case Numops: case Ocjmp:
+ case Obad: case Ocjmp:
case Oload: case Ostor:
case Oslbase: case Osllen:
+ case Oblit: case Numops:
die("Should not see %s in fe", opstr(exprop(n)));
break;
}
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -52,5 +52,6 @@
O(Ocjmp, 1) /* conditional jump */
O(Oload, 1) /* load from memory */
O(Ostor, 1) /* store to memory */
-O(Osllen, 1)
-O(Oslbase, 1)
+O(Osllen, 1) /* size of slice */
+O(Oslbase, 1) /* base of sice */
+O(Oblit, 1) /* block copy of memory */