diff options
| author | 2026-03-22 19:25:46 +0100 | |
|---|---|---|
| committer | 2026-03-22 19:25:46 +0100 | |
| commit | cbca5355c0c0b1910735b1430e2552855a2aa5c7 (patch) | |
| tree | 7a0e0452f8dba566a5c7c0ed20dc4a60084bbea8 | |
| parent | 2d0b096a8c2f45370ef2535e1c500a008b949611 (diff) | |
aarch64: rem/urem, bswap*, arg bugfix
| -rw-r--r-- | src/ir_op.def | 3 | ||||
| -rw-r--r-- | src/ir_regalloc.c | 12 | ||||
| -rw-r--r-- | src/t_aarch64_emit.c | 22 | ||||
| -rw-r--r-- | src/t_aarch64_isel.c | 40 | ||||
| -rwxr-xr-x | test/run.sh | 2 |
5 files changed, 67 insertions, 12 deletions
diff --git a/src/ir_op.def b/src/ir_op.def index 4e775a1..dde4e10 100644 --- a/src/ir_op.def +++ b/src/ir_op.def @@ -75,5 +75,6 @@ _(phi, 1) _(swap, 2) _(vastart, 1) _(vaarg, 2) -/* machine-specific instructions */ +/* machine-specific/internal instructions */ _(xvaprologue, 1) +_(msub, 3) diff --git a/src/ir_regalloc.c b/src/ir_regalloc.c index 41a4026..3b204c6 100644 --- a/src/ir_regalloc.c +++ b/src/ir_regalloc.c @@ -725,9 +725,9 @@ buildintervals(RegAlloc *ra) queue[0] = ins->r; } else { switch ((nqueue = opnarg[ins->op])) { - case 2: queue[2] = ins->oper[2]; - case 1: queue[1] = ins->oper[1]; - case 0: queue[0] = ins->oper[0]; + case 3: queue[2] = ins->oper[2]; + case 2: queue[1] = ins->oper[1]; + case 1: queue[0] = ins->oper[0]; } } if (0) { @@ -1148,15 +1148,15 @@ devirt(RegAlloc *ra, Block *blk) Interval *it; Alloc *alloc; IRAddr newaddr; - Ref *argref[4]; + Ref *argref[6]; int curi0; int naddr = 0; int nargref = 0; int nspill = 0; /** devirtualize operands **/ - for (int i = 0; i < 2; ++i) { - Ref *r = &i[&ins->l]; + for (int i = 0; i < 3; ++i) { + Ref *r = &ins->oper[i]; if (r->t == RADDR) { IRAddr *a = &addrtab.p[r->i]; ++naddr; diff --git a/src/t_aarch64_emit.c b/src/t_aarch64_emit.c index 4679569..abf1f3e 100644 --- a/src/t_aarch64_emit.c +++ b/src/t_aarch64_emit.c @@ -227,6 +227,9 @@ encode(uchar **pcode, const EncDesc *tab, int ntab, enum irclass k, Oper o[3]) case EN_ADDSUBSHFT3R: 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_ARITH2R: + ins |= sf<<31 | 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; @@ -352,6 +355,15 @@ Xmadd(uchar **pcode, enum irclass k, Oper d, Oper n, Oper m, Oper a) W32(0x1B000000 | sf<<31 | m.reg<<16 | a.reg<<10 | n.reg<<5 | d.reg); } +static void +Xmsub(uchar **pcode, enum irclass k, Oper d, Oper n, Oper m, Oper a) +{ + assert(opermatch(PGPRZ, k, d) && opermatch(PGPRZ, k, n) + && opermatch(PGPRZ, k, a) && opermatch(PGPRZ, k, m)); + uint sf = k > KI32; + W32(0x1B008000 | 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}) @@ -515,6 +527,10 @@ DEFINSTR2(Xfcmp, {4|8, {PFPR, PZERO}, 0x1E602008, EN_FPCMPZ}, {4|8, {PFPR, PFPR}, 0x1E602000, EN_FPCMP}, ) +DEFINSTR2(Xrev, + {4 , {PGPRZ, PGPRZ}, 0x5AC00800, EN_ARITH2R}, + { 8, {PGPRZ, PGPRZ}, 0xDAC00C00, EN_ARITH2R}, +) static void gencopy(uchar **pcode, enum irclass cls, Block *blk, int curi, Oper dst, Ref val) @@ -744,12 +760,18 @@ emitinstr(uchar **pcode, Function *fn, Block *blk, int curi, Instr *ins) Cvt: X2(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l)); break; + case Obswap32: case Obswap64: + Xrev(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l)); + break; case Oadd: X3 = kisint(cls) ? Xadd : Xfadd; goto ALU3; case Osub: X3 = kisint(cls) ? Xsub : Xfsub; goto ALU3; case Omul: if (kisflt(cls)) { X3 = Xfmul; goto ALU3; } /* 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 Omsub: + Xmsub(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), ref2oper(ins->r), ref2oper(ins->oper[2])); + break; case Odiv: X3 = kisint(cls) ? Xsdiv : Xfdiv; goto ALU3; case Oudiv: X3 = Xudiv; goto ALU3; case Oand: X3 = Xand; goto ALU3; diff --git a/src/t_aarch64_isel.c b/src/t_aarch64_isel.c index 381a57d..29056bc 100644 --- a/src/t_aarch64_isel.c +++ b/src/t_aarch64_isel.c @@ -137,7 +137,15 @@ fixarg(Ref *r, Instr *ins, Block *blk, int *curi) else *r = insertinstr(blk, (*curi)++, adr); } else if (r->t != RTMP) Reg: { - regarg(r, r->t == RTMP ? instrtab[r->i].cls : ins->cls ? ins->cls : KI32, blk, curi); + enum irclass k; + if (r->t == RTMP) k = insrescls(instrtab[r->i]); + else if (ins->op == Oarg) { + IRType ty = ref2type(ins->l); + k = ty.isagg ? KPTR : ty.cls; + } else { + k = ins->cls; + } + regarg(r, k, blk, curi); } } @@ -351,8 +359,9 @@ loadstoreaddr(Block *blk, Ref *r, int *curi, enum op op) static void sel(Function *fn, Instr *ins, Block *blk, int *curi) { - enum op op = ins->op; + Ref tmp; enum irclass cls; + enum op op = ins->op; if (oisarith(ins->op) && arithfold(ins)) { fixarg(&ins->l, ins, blk, curi); @@ -390,6 +399,18 @@ sel(Function *fn, Instr *ins, Block *blk, int *curi) regarg(&ins->l, ins->cls, blk, curi); ins->op = Ocopy; break; + case Obswap32: case Obswap64: + regarg(&ins->l, ins->cls, blk, curi); + break; + case Obswap16: + /* %tmp = rev %x + * %res = lsr %tmp, 16 */ + regarg(&ins->l, ins->cls, blk, curi); + tmp = insertinstr(blk, (*curi)++, mkinstr1(Obswap32, KI32, ins->l)); + ins->op = Oslr; + ins->l = tmp; + ins->r = mkref(RICON, 16); + break; case Oadd: if (isnumcon(ins->l)) { /* swap to have const in rhs */ @@ -409,7 +430,7 @@ sel(Function *fn, Instr *ins, Block *blk, int *curi) case Oand: case Oior: case Oxor: if (isnumcon(ins->l)) { /* swap to have const in rhs */ - Ref tmp = ins->l; + tmp = ins->l; ins->l = ins->r; ins->r = tmp; } @@ -421,9 +442,20 @@ sel(Function *fn, Instr *ins, Block *blk, int *curi) regarg(&ins->l, ins->cls, blk, curi); fixarg(&ins->r, ins, blk, curi); break; - case Omul: case Odiv: case Oudiv: case Ourem: + case Omul: case Odiv: case Oudiv: + regarg(&ins->l, ins->cls, blk, curi); + regarg(&ins->r, ins->cls, blk, curi); + break; + case Orem: case Ourem: regarg(&ins->l, ins->cls, blk, curi); regarg(&ins->r, ins->cls, blk, curi); + /* %tmp = div %l, %r + * %res = msub %tmp, %r, %l */ + tmp = insertinstr(blk, (*curi)++, + mkinstr2(op == Orem ? Odiv : Oudiv, ins->cls, ins->l, ins->r)); + ins->op = Omsub; + ins->oper[2] = ins->l; + ins->oper[0] = tmp; break; case Oarg: fixarg(&ins->r, ins, blk, curi); diff --git a/test/run.sh b/test/run.sh index ec40161..07f967e 100755 --- a/test/run.sh +++ b/test/run.sh @@ -26,7 +26,7 @@ run() { echo '-------' else actual=build/"$(echo "$f" | sed 's/\.c$/.actual/')" - x "$exe" $args > "$actual" + x $QEMU "$exe" $args > "$actual" if ! cmp "$actual" "$expected" > /dev/null; then echo --- !TEST ERROR "$f" diff --unified=0 "$expected" "$actual" |