From 2b6b6b79beba618ab46c353a59a1c90539340021 Mon Sep 17 00:00:00 2001 From: lemon Date: Tue, 30 Dec 2025 09:53:53 +0100 Subject: aarch64 mul/div --- aarch64/emit.c | 25 +++++++++++++++++++++++++ aarch64/isel.c | 6 ++++++ 2 files changed, 31 insertions(+) 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: -- cgit v1.2.3