aboutsummaryrefslogtreecommitdiff
path: root/amd64
diff options
context:
space:
mode:
authorEyal Sawady <[email protected]>2022-01-17 22:00:48 +0000
committerQuentin Carbonneaux <[email protected]>2022-01-23 11:43:59 +0100
commite91d12158122b23271ff49de8977c92fef7f3908 (patch)
treeea5051ef69ae917f23249fe7a6adc8569deb3718 /amd64
parent367c8215d99054892740ad74c690b106c45ebf60 (diff)
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.c29
-rw-r--r--amd64/isel.c1
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: