diff options
-rw-r--r-- | amd64/emit.c | 29 | ||||
-rw-r--r-- | amd64/isel.c | 1 | ||||
-rw-r--r-- | arm64/emit.c | 2 | ||||
-rw-r--r-- | doc/il.txt | 1 | ||||
-rw-r--r-- | fold.c | 3 | ||||
-rw-r--r-- | ops.h | 1 | ||||
-rw-r--r-- | parse.c | 2 | ||||
-rw-r--r-- | tools/lexh.c | 2 |
8 files changed, 28 insertions, 13 deletions
diff --git a/amd64/emit.c b/amd64/emit.c index a888000..4cb340d 100644 --- a/amd64/emit.c +++ b/amd64/emit.c @@ -365,6 +365,7 @@ emitins(Ins i, Fn *fn, FILE *f) Ref r; int64_t val; int o, t0; + Ins ineg; switch (i.op) { default: @@ -376,7 +377,7 @@ emitins(Ins i, Fn *fn, FILE *f) /* this linear search should really be a binary * search */ if (omap[o].op == NOp) - die("no match for %s(%d)", + die("no match for %s(%c)", optab[i.op].name, "wlsd"[i.cls]); if (omap[o].op == i.op) if (omap[o].cls == i.cls @@ -409,20 +410,26 @@ emitins(Ins i, Fn *fn, FILE *f) /* we have to use the negation trick to handle * some 3-address subtractions */ if (req(i.to, i.arg[1]) && !req(i.arg[0], i.to)) { - if (KBASE(i.cls) == 0) - emitf("neg%k %=", &i, fn, f); - else - fprintf(f, - "\txorp%c %sfp%d(%%rip), %%%s\n", - "xxsd"[i.cls], - gasloc, - gasstash(negmask[i.cls], 16), - regtoa(i.to.val, SLong) - ); + ineg = (Ins){Oneg, i.cls, i.to, {i.to}}; + emitins(ineg, fn, f); emitf("add%k %0, %=", &i, fn, f); break; } goto Table; + case Oneg: + if (!req(i.to, i.arg[0])) + emitf("mov%k %0, %=", &i, fn, f); + if (KBASE(i.cls) == 0) + emitf("neg%k %=", &i, fn, f); + else + fprintf(f, + "\txorp%c %sfp%d(%%rip), %%%s\n", + "xxsd"[i.cls], + gasloc, + gasstash(negmask[i.cls], 16), + regtoa(i.to.val, SLong) + ); + break; case Odiv: /* use xmm15 to adjust the instruction when the * conversion to 2-address in emitf() would fail */ diff --git a/amd64/isel.c b/amd64/isel.c index 0f4c7a5..404b714 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -290,6 +290,7 @@ sel(Ins i, ANum *an, Fn *fn) case Ocopy: case Oadd: case Osub: + case Oneg: case Omul: case Oand: case Oor: diff --git a/arm64/emit.c b/arm64/emit.c index bd0ebdc..de1859b 100644 --- a/arm64/emit.c +++ b/arm64/emit.c @@ -43,6 +43,8 @@ static struct { { Oadd, Ka, "fadd %=, %0, %1" }, { Osub, Ki, "sub %=, %0, %1" }, { Osub, Ka, "fsub %=, %0, %1" }, + { Oneg, Ki, "neg %=, %0" }, + { Oneg, Ka, "fneg %=, %0" }, { Oand, Ki, "and %=, %0, %1" }, { Oor, Ki, "orr %=, %0, %1" }, { Oxor, Ki, "eor %=, %0, %1" }, diff --git a/doc/il.txt b/doc/il.txt index 87a4d9f..48ecb23 100644 --- a/doc/il.txt +++ b/doc/il.txt @@ -524,6 +524,7 @@ return type used is long, the argument must be of type double. ~~~~~~~~~~~~~~~~~~~~~ * `add`, `sub`, `div`, `mul` -- `T(T,T)` + * `neg` -- `T(T)` * `udiv`, `rem`, `urem` -- `I(I,I)` * `or`, `xor`, `and` -- `I(I,I)` * `sar`, `shr`, `shl` -- `I(I,ww)` diff --git a/fold.c b/fold.c index 348e532..9923f75 100644 --- a/fold.c +++ b/fold.c @@ -368,6 +368,7 @@ foldint(Con *res, int op, int w, Con *cl, Con *cr) switch (op) { case Oadd: x = l.u + r.u; break; case Osub: x = l.u - r.u; break; + case Oneg: x = -l.u; break; case Odiv: x = w ? l.s / r.s : (int32_t)l.s / (int32_t)r.s; break; case Orem: x = w ? l.s % r.s : (int32_t)l.s % (int32_t)r.s; break; case Oudiv: x = w ? l.u / r.u : (uint32_t)l.u / (uint32_t)r.u; break; @@ -464,6 +465,7 @@ foldflt(Con *res, int op, int w, Con *cl, Con *cr) switch (op) { case Oadd: xd = ld + rd; break; case Osub: xd = ld - rd; break; + case Oneg: xd = -ld; break; case Odiv: xd = ld / rd; break; case Omul: xd = ld * rd; break; case Oswtof: xd = (int32_t)cl->bits.i; break; @@ -480,6 +482,7 @@ foldflt(Con *res, int op, int w, Con *cl, Con *cr) switch (op) { case Oadd: xs = ls + rs; break; case Osub: xs = ls - rs; break; + case Oneg: xs = -ls; break; case Odiv: xs = ls / rs; break; case Omul: xs = ls * rs; break; case Oswtof: xs = (int32_t)cl->bits.i; break; diff --git a/ops.h b/ops.h index 535be71..0729d46 100644 --- a/ops.h +++ b/ops.h @@ -15,6 +15,7 @@ /* Arithmetic and Bits */ O(add, T(w,l,s,d, w,l,s,d), 1) X(2, 1, 0) O(sub, T(w,l,s,d, w,l,s,d), 1) X(2, 1, 0) +O(neg, T(w,l,s,d, x,x,x,x), 1) X(1, 1, 0) O(div, T(w,l,s,d, w,l,s,d), 1) X(0, 0, 0) O(rem, T(w,l,e,e, w,l,e,e), 1) X(0, 0, 0) O(udiv, T(w,l,e,e, w,l,e,e), 1) X(0, 0, 0) diff --git a/parse.c b/parse.c index 6e22e1f..c05c370 100644 --- a/parse.c +++ b/parse.c @@ -109,7 +109,7 @@ enum { TMask = 16383, /* for temps hash */ BMask = 8191, /* for blocks hash */ - K = 3233235, /* found using tools/lexh.c */ + K = 4331239, /* found using tools/lexh.c */ M = 23, }; diff --git a/tools/lexh.c b/tools/lexh.c index 2ebb022..3c5ae24 100644 --- a/tools/lexh.c +++ b/tools/lexh.c @@ -8,7 +8,7 @@ char *tok[] = { - "add", "sub", "div", "rem", "udiv", "urem", "mul", + "add", "sub", "neg", "div", "rem", "udiv", "urem", "mul", "and", "or", "xor", "sar", "shr", "shl", "stored", "stores", "storel", "storew", "storeh", "storeb", "load", "loadsw", "loaduw", "loadsh", "loaduh", |