aboutsummaryrefslogtreecommitdiff
path: root/simpl.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2022-12-10 23:16:21 +0100
committerQuentin Carbonneaux <[email protected]>2022-12-14 23:18:26 +0100
commit26c1c30b7d96d2170195970a8cdb3b024ba7421a (patch)
tree79c45ec28d63619fbe2a88ec2195f8fe4a95a8a5 /simpl.c
parent15e25a61b38b250c7543437a093a9efe076cce0a (diff)
new blit instruction
Diffstat (limited to 'simpl.c')
-rw-r--r--simpl.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/simpl.c b/simpl.c
new file mode 100644
index 0000000..7001301
--- /dev/null
+++ b/simpl.c
@@ -0,0 +1,82 @@
+#include "all.h"
+
+static void
+blit(Ref sd[2], int sz, Fn *fn)
+{
+ struct { int st, ld, cls, size; } *p, tbl[] = {
+ { Ostorel, Oload, Kl, 8 },
+ { Ostorew, Oload, Kw, 4 },
+ { Ostoreh, Oloaduh, Kw, 2 },
+ { Ostoreb, Oloadub, Kw, 1 }
+ };
+ Ref r, r1, ro;
+ int off, fwd, n;
+
+ fwd = sz >= 0;
+ sz = abs(sz);
+ off = fwd ? sz : 0;
+ for (p=tbl; sz; p++)
+ for (n=p->size; sz>=n; sz-=n) {
+ off -= fwd ? n : 0;
+ r = newtmp("blt", Kl, fn);
+ r1 = newtmp("blt", Kl, fn);
+ ro = getcon(off, fn);
+ emit(p->st, 0, R, r, r1);
+ emit(Oadd, Kl, r1, sd[1], ro);
+ r1 = newtmp("blt", Kl, fn);
+ emit(p->ld, p->cls, r, r1, R);
+ emit(Oadd, Kl, r1, sd[0], ro);
+ off += fwd ? 0 : n;
+ }
+}
+
+static void
+ins(Ins **pi, int *new, Blk *b, Fn *fn)
+{
+ ulong ni;
+ Ins *i;
+
+ i = *pi;
+ /* simplify more instructions here;
+ * copy 0 into xor, mul 2^n into shift,
+ * bit rotations, ... */
+ switch (i->op) {
+ case Oblit1:
+ assert(i > b->ins);
+ assert((i-1)->op == Oblit0);
+ if (!*new) {
+ curi = &insb[NIns];
+ ni = &b->ins[b->nins] - (i+1);
+ curi -= ni;
+ icpy(curi, i+1, ni);
+ *new = 1;
+ }
+ blit((i-1)->arg, rsval(i->arg[0]), fn);
+ *pi = i-1;
+ break;
+ default:
+ if (*new)
+ emiti(*i);
+ break;
+ }
+}
+
+void
+simpl(Fn *fn)
+{
+ Blk *b;
+ Ins *i;
+ int new;
+
+ for (b=fn->start; b; b=b->link) {
+ new = 0;
+ for (i=&b->ins[b->nins]; i!=b->ins;) {
+ --i;
+ ins(&i, &new, b, fn);
+ }
+ if (new) {
+ b->nins = &insb[NIns] - curi;
+ idup(&b->ins, curi, b->nins);
+ }
+ }
+}