aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-12-30 09:53:53 +0100
committerlemon <lsof@mailbox.org>2025-12-30 09:53:53 +0100
commit2b6b6b79beba618ab46c353a59a1c90539340021 (patch)
tree4200a1a7c81a95ff03e13fc7b6daaafe82f5909f
parent5559e5fc1f6c10d88eb32febc3a36a8fc2502d58 (diff)
aarch64 mul/div
-rw-r--r--aarch64/emit.c25
-rw-r--r--aarch64/isel.c6
2 files changed, 31 insertions, 0 deletions
diff --git a/aarch64/emit.c b/aarch64/emit.c
index b1700c3..217fef9 100644
--- a/aarch64/emit.c
+++ b/aarch64/emit.c
@@ -220,6 +220,9 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o
case EN_LOGSHFT3R:
ins |= sf<<31 | o[2].shft<<22 | o[2].reg<<16 | o[2].shamt<<10 | o[1].reg<<5 | o[0].reg;
break;
+ case EN_ARITH3R:
+ ins |= sf<<31 | o[2].reg<<16 | o[1].reg<<5 | o[0].reg;
+ break;
case EN_ADDSUBIMM:
sh = o[2].imm > 0xFFF;
ins |= sf<<31 | sh<<22 | (o[2].uimm >> 12*sh)<<10 | o[1].reg<<5 | o[0].reg;
@@ -313,6 +316,18 @@ DEFINSTR3(Xsubs,
{4|8, {PGPRZ, PGPRZ, PGPRZSHFT}, 0x6B000000, EN_ADDSUBSHFT3R}, /* SUBS (shifted register) */
)
+static void
+Xmadd(uchar **pcode, enum irclass k, struct oper d, struct oper n, struct oper m, struct oper a)
+{
+ assert(opermatch(PGPRZ, k, d) && opermatch(PGPRZ, k, n)
+ && opermatch(PGPRZ, k, a) && opermatch(PGPRZ, k, m));
+ uint sf = k > KI32;
+ W32(0x1B000000 | sf<<31 | m.reg<<16 | a.reg<<10 | n.reg<<5 | d.reg);
+}
+
+DEFINSTR3(Xsdiv, {4|8, {PGPRZ, PGPRZ, PGPRZ}, 0x1AC00C00, EN_ARITH3R})
+DEFINSTR3(Xudiv, {4|8, {PGPRZ, PGPRZ, PGPRZ}, 0x1AC00800, EN_ARITH3R})
+
DEFINSTR3(Xand,
{4|8, {PGPRSP, PGPRZ, PLOGIMM}, 0x12000000, EN_LOGIMM}, /* AND (immediate) */
{4|8, {PGPRZ, PGPRZ, PGPRZSHFT}, 0x0A000000, EN_LOGSHFT3R}, /* AND (shifted register) */
@@ -610,6 +625,16 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
ALU3:
X3(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), ref2oper(ins->r));
break;
+ case Omul:
+ /* MUL Rd,Rn,Rm ==> MADD Rd,Rn,Rm,zr */
+ Xmadd(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), ref2oper(ins->r), REGZR);
+ break;
+ case Odiv:
+ Xsdiv(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), ref2oper(ins->r));
+ break;
+ case Oudiv:
+ Xudiv(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), ref2oper(ins->r));
+ break;
case Oshl:
if (ins->r.t == RICON) {
uint nbit = cls == KI32 ? 32 : 64, s = ins->r.i & nbit-1;
diff --git a/aarch64/isel.c b/aarch64/isel.c
index 239d1cd..5a8c67b 100644
--- a/aarch64/isel.c
+++ b/aarch64/isel.c
@@ -334,6 +334,12 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
case Oshl: case Osar: case Oslr:
fixarg(&ins->r, ins, blk, curi);
break;
+ case Omul: case Odiv:
+ if (ins->l.t != RTMP)
+ ins->l = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ins->cls, ins->l));
+ if (ins->r.t != RTMP)
+ ins->r = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ins->cls, ins->r));
+ break;
case Oequ: case Oneq:
case Olth: case Ogth: case Olte: case Ogte:
case Oulth: case Ougth: case Oulte: case Ougte: