diff options
author | Eyal Sawady <ecs@d2evs.net> | 2022-01-17 22:00:48 +0000 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2022-01-23 11:43:59 +0100 |
commit | e91d12158122b23271ff49de8977c92fef7f3908 (patch) | |
tree | ea5051ef69ae917f23249fe7a6adc8569deb3718 /amd64 | |
parent | 367c8215d99054892740ad74c690b106c45ebf60 (diff) | |
download | roux-e91d12158122b23271ff49de8977c92fef7f3908.tar.gz |
Add a negation instruction
Necessary for floating-point negation, because `%result = sub 0, %operand` doesn't give the correct sign for 0/-0.
Diffstat (limited to 'amd64')
-rw-r--r-- | amd64/emit.c | 29 | ||||
-rw-r--r-- | amd64/isel.c | 1 |
2 files changed, 19 insertions, 11 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: |