aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-12 22:14:45 +0200
committerlemon <lsof@mailbox.org>2023-06-12 22:16:34 +0200
commita5bb980335f5234f4901ae062e183e5bb72f845f (patch)
tree716bff8a3fa3ebfc7f29cab3d89be64097dae0b7
parent906550167df51dd29a778ac79b7ec95d891b80ad (diff)
xor reg,reg
-rw-r--r--amd64/emit.c16
-rw-r--r--amd64/isel.c13
-rw-r--r--test/test3.c5
3 files changed, 29 insertions, 5 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index c1f01a3..f872b49 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -238,10 +238,10 @@ DEFINSTR2(Xmov,
{4|8, PGPR, PMEM, "\x8B", EN_RM}, /* MOV r32/64, m32/64 */
{4|8, PGPR, PI32, "\xB8", EN_OI}, /* MOV r32/64, imm */
{4, PFPR, PFPR, "\xF3\x0F\x10", EN_RR}, /* MOVSS xmm, xmm */
- {4, PFPR, PMEM, "\xF3\x0F\x10", EN_RM}, /* MOVSS xmm, m32 */
- {4, PMEM, PFPR, "\xF3\x0F\x10", EN_MR}, /* MOVSS m32, xmm */
{8, PFPR, PFPR, "\xF2\x0F\x10", EN_RR}, /* MOVSD xmm, xmm */
+ {4, PFPR, PMEM, "\xF3\x0F\x10", EN_RM}, /* MOVSS xmm, m32 */
{8, PFPR, PMEM, "\xF2\x0F\x10", EN_RM}, /* MOVSD xmm, m64 */
+ {4, PMEM, PFPR, "\xF3\x0F\x10", EN_MR}, /* MOVSS m32, xmm */
{8, PMEM, PFPR, "\xF2\x0F\x11", EN_MR}, /* MOVSS m64, xmm */
)
DEFINSTR2(Xmovsx4,
@@ -291,6 +291,14 @@ DEFINSTR2(Xsub,
{4, PFPR, PMEM, "\xF3\x0F\x5C", EN_RM}, /* SUBSS xmm, m32 */
{8, PFPR, PMEM, "\xF2\x0F\x5C", EN_RM}, /* SUBSD xmm, m64 */
)
+DEFINSTR2(Xxor,
+ {4|8, PGPR, PGPR, "\x33", EN_RR}, /* XOR r32/64, r32/64 */
+ {4|8, PGPR, PI8, "\x83", EN_RI8, .ext=6}, /* XOR r32/64, imm8 */
+ {4|8, PRAX, PI32, "\x35", EN_I32}, /* XOR eax/rax, imm */
+ {4|8, PGPR, PI32, "\x81", EN_RI32, .ext=6}, /* XOR r32/64, imm */
+ { 8, PGPR, PMEM, "\x33", EN_RM}, /* XOR r64, m64 */
+ {4|8, PFPR, PFPR, "\x0F\x57", EN_RR}, /* XORPS xmm, xmm */
+)
DEFINSTR2(Xshl,
{4|8, PGPR, P1, "\xD1", EN_R, .ext=4}, /* SHL r32/64, 1 */
{4|8, PGPR, PI32, "\xC1", EN_RI8, .ext=4}, /* SHL r32/64, imm */
@@ -431,10 +439,12 @@ gencopy(uchar **pcode, enum irclass cls, struct oper dst, union ref val)
/* normal (not 2-address) case */
Lea:
Xlea(pcode, cls2siz[cls], dst, ref2oper(val));
+ } else if (val.t == RICON && val.i == 0 && dst.t == OREG) {
+ Xxor(pcode, cls2siz[cls], dst, dst);
} else if (val.t == RXCON && conht[val.i].isdat && !conht[val.i].deref) {
Xlea(pcode, cls2siz[cls], dst, mkoper(OCONR, .con = val.i));
} else {
- struct oper src = mkimmregoper(val);
+ struct oper src = mkimmdatregoper(val);
if (memcmp(&dst, &src, sizeof dst) != 0)
Xmov(pcode, cls2siz[cls], dst, src);
}
diff --git a/amd64/isel.c b/amd64/isel.c
index 30ad222..858dfbc 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -17,7 +17,12 @@ fixarg(struct function *fn, union ref *r, struct instr *ins, struct block *blk,
/* add X, INT32MAX+1 -> sub X, INT32MIN */
ins->op = Oadd + (op == Oadd);
*r = mkintcon(fn, KI4, -2147483648);
- } else if (con->cls && (kisflt(con->cls) || con->cls == KI8)) {
+ } else if (in_range(op, Ocopy, Omove) && kisflt(con->cls)
+ && (con->cls == KF4 ? con->fs == 0.0f : con->fd == 0.0))
+ {
+ /* copy of float zero -> regular zero, that emit() will turn into xor x,x */
+ *r = mkref(RICON, 0);
+ } else if (kisflt(con->cls) || con->cls == KI8) {
/* float immediates & >32b immediates are loaded from memory */
uchar data[8];
uint siz = cls2siz[con->cls];
@@ -140,6 +145,11 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
enum op op = ins->op;
switch (op) {
+ default: assert(0);
+ case Onop: break;
+ case Oalloca1: case Oalloca2: case Oalloca4: case Oalloca8: case Oalloca16:
+ case Ocall: case Ointrin:
+ break;
case Oshl: case Osar: case Oslr:
if (!iscon(ins->r)) {
/* shift amount register is always CL */
@@ -222,6 +232,7 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
if (ins->l.t != RTMP && ins->l.t != RREG)
ins->l = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ins->cls, ins->l));
if (ins->r.t)
+ case Omove:
fixarg(fn, &ins->r, ins, blk, curi);
break;
case Oloads1: case Oloadu1: case Oloads2: case Oloadu2:
diff --git a/test/test3.c b/test/test3.c
index 8bd9020..74f4c00 100644
--- a/test/test3.c
+++ b/test/test3.c
@@ -12,10 +12,13 @@ int shcl(int a, int b) {
return a << (b+1);
}
+int zero() { return 0; }
+float fzero() { return 0.0f; }
+
struct p { long x,y; };
struct p divsh(int a) {
struct p p;
- p.x = a << (a / 5);
+ p.x = a << (a % 5);
p.y = a;
return p;
}