commit a500905ef3ff90575cfd19caa02178810ebb92e6
parent fe6a9fbc790e657a4dce00fdccfd72f5c235a3c9
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Mon, 9 Dec 2024 11:04:03 +0100
cc2/qbe: Use the neg instruction
Qbe didn't support negation and it had to be calculated
using the substraction from 0, but this generated different
problems (specially with floating point numbers), and for
that reason it was added to the language.
Diffstat:
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/src/cmd/scc-cc/cc2/qbe/arch.h b/src/cmd/scc-cc/cc2/qbe/arch.h
@@ -119,6 +119,11 @@ enum asmop {
ASEXTS,
ASTRUNCD,
+ ASNEGL,
+ ASNEGW,
+ ASNEGS,
+ ASNEGD,
+
ASJMP,
ASBRANCH,
ASRET,
diff --git a/src/cmd/scc-cc/cc2/qbe/cgen.c b/src/cmd/scc-cc/cc2/qbe/cgen.c
@@ -29,6 +29,7 @@ static unsigned char opasmw[][2] = {
[OBAND] = {ASBANDW, ASBANDW},
[OBOR] = {ASBORW, ASBORW},
[OBXOR] = {ASBXORW, ASBXORW},
+ [OSNEG] = {ASNEGW, ASNEGW},
};
static unsigned char opasml[][2] = {
@@ -48,6 +49,7 @@ static unsigned char opasml[][2] = {
[OBAND] = {ASBANDL, ASBANDL},
[OBOR] = {ASBORL, ASBORL},
[OBXOR] = {ASBXORL, ASBXORL},
+ [OSNEG] = {ASNEGL, ASNEGL},
};
static unsigned char opasms[][2] = {
@@ -61,6 +63,7 @@ static unsigned char opasms[][2] = {
[OGE] = {ASGES, ASGES},
[OEQ] = {ASEQS, ASEQS},
[ONE] = {ASNES, ASNES},
+ [OSNEG] = {ASNEGS, ASNEGS},
};
static unsigned char opasmd[][2] = {
@@ -74,6 +77,7 @@ static unsigned char opasmd[][2] = {
[OGE] = {ASGED, ASGED},
[OEQ] = {ASEQD, ASEQD},
[ONE] = {ASNED, ASNED},
+ [OSNEG] = {ASNEGD, ASNEGD},
};
static unsigned char (*opbin[][2])[2] = {
@@ -183,12 +187,6 @@ sethi(Node *np)
np->op = OBXOR;
rp = constnode(NULL, ~(TUINT) 0, &np->type);
goto binary;
- case OSNEG:
- np->op = OSUB;
- rp = lp;
- lp = constnode(NULL, 0, &np->type);
- if ((np->type.flags & INTF) == 0)
- lp->u.f = 0.0;
default:
binary:
lp = sethi(lp);
@@ -719,6 +717,14 @@ rhs(Node *np)
case OCOMMA:
rhs(l);
return rhs(r);
+ case OSNEG:
+ sign = (tp->flags & SIGNF) == 0;
+ size = tp->size == 8;
+ isfloat = (tp->flags & FLOATF) != 0;
+ op = opbin[isfloat][size][np->op][sign];
+ tmp = tmpnode(tp);
+ code(op, tmp, rhs(l), NULL);
+ return tmp;
case OPTR:
return load(tp, rhs(l));
case OADDR:
diff --git a/src/cmd/scc-cc/cc2/qbe/code.c b/src/cmd/scc-cc/cc2/qbe/code.c
@@ -147,6 +147,11 @@ static struct opdata {
[ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
[ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
+ [ASNEGL] = {.fun = unary, .txt = "neg", .letter ='l'},
+ [ASNEGW] = {.fun = unary, .txt = "neg", .letter ='w'},
+ [ASNEGS] = {.fun = unary, .txt = "neg", .letter ='s'},
+ [ASNEGD] = {.fun = unary, .txt = "neg", .letter ='d'},
+
[ASBRANCH] = {.fun = branch},
[ASJMP] = {.fun = jmp},
[ASRET] = {.fun = ret},