From 12974932af785a2ab2cefb5bc80da3ee1211e3c3 Mon Sep 17 00:00:00 2001 From: lemon Date: Fri, 2 Jan 2026 14:40:06 +0100 Subject: aarch64: LDR literal, cmp value --- aarch64/emit.c | 41 +++++++++++++++++++++++++++++++---------- obj/elf.c | 2 ++ obj/obj.h | 1 + 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/aarch64/emit.c b/aarch64/emit.c index 11ee552..8fe3677 100644 --- a/aarch64/emit.c +++ b/aarch64/emit.c @@ -51,6 +51,8 @@ mkmemoper(uint msiz, union ref r) return mkoper(OMEM, .m = {AIMMIDX, .base = instrtab[r.i].reg-1}); } else if (r.t == RREG) { return mkoper(OMEM, .m = {AIMMIDX, .base = r.i}); + } else if (isaddrcon(r,1)) { + return mkoper(OSYM, .con = r.i,); } else if (r.t == RADDR) { const struct addr *addr = &addrht[r.i]; assert(addr->shift <= 3 && (!addr->disp || !addr->index.bits)); @@ -137,12 +139,13 @@ enum operenc { EN_ADRSYMLO21, /* for ADR */ EN_ADRSYMPGHI21, /* for ADRP */ EN_ADDSYMLO12, /* for ADD x,x, */ - EN_FP2R, - EN_FP1GPR1, - EN_FP3R, - EN_FPIMM, - EN_FPCMPZ, - EN_FPCMP, + EN_LDSYMLO19, /* for LDR (literal) */ + EN_FP2R, /* float 1src */ + EN_FP1GPR1, /* fpr + gpr */ + EN_FP3R, /* float 2src */ + EN_FPIMM, /* float-imm */ + EN_FPCMPZ, /* float cmp with zero */ + EN_FPCMP, /* float cmp-imm */ }; struct desc { uchar psiz; /* subset of {4,8} */ @@ -273,6 +276,10 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o ins |= sf<<31 | o[1].reg<<5 | o[0].reg; objreloc(xcon2sym(o[2].con), REL_ADD_ABS_LO12_NC, Stext, *pcode - objout.textbegin, o[1].cdisp); break; + case EN_LDSYMLO19: + ins |= o[0].reg; + objreloc(xcon2sym(o[1].con), REL_LD_PREL_LO19, Stext, *pcode - objout.textbegin, o[1].cdisp); + break; case EN_FP2R: ins |= sf<<22 | (o[1].reg&31)<<5 | (o[0].reg&31); break; @@ -385,6 +392,8 @@ DEFINSTR2(Xldr, {8, {PGPRZ, PMEMAIMMX}, 0xF9400000, EN_MEMAIMMX}, {4, {PGPRZ, PMEMAREG}, 0xB8600800, EN_MEMAREG}, /* LDR (register) */ {8, {PGPRZ, PMEMAREG}, 0xF8600800, EN_MEMAREG}, + {4, {PGPRZ, PSYM}, 0x18000000, EN_LDSYMLO19}, /* LDR (literal) */ + {8, {PGPRZ, PSYM}, 0x58000000, EN_LDSYMLO19}, {4, {PGPRZ, PMEMPREPOST}, 0xB8400000, EN_MEMAPREPOST}, /* LDR (immediate, (pre/postinc)) */ {8, {PGPRZ, PMEMPREPOST}, 0xF8400000, EN_MEMAPREPOST}, ) @@ -634,6 +643,8 @@ emitbranch(uchar **pcode, struct block *blk) Xbcc(pcode, CCAL, blk->s2); } +static struct instr *lastcmp; + static void emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struct instr *ins) { @@ -726,12 +737,21 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc case Oequ: case Oneq: if (!ins->reg && kisint(cls) && ins->r.bits == ZEROREF.bits) break; /* handled by emitbranch for CBZ/CBNZ */ case Olth: case Ogth: case Olte: case Ogte: - if (kisflt(cls)) - Xfcmp(pcode, cls, ref2oper(ins->l), ref2oper(ins->r)); - else case Oulth: case Ougth: case Oulte: case Ougte: - /* CMP ... ==> SUBS zr, ... */ + if (lastcmp && lastcmp->cls == cls + && lastcmp->l.bits == ins->l.bits && lastcmp->r.bits == ins->r.bits) + /* reuse flags from previous identical cmp */ ; + else if (kisflt(cls)) + Xfcmp(pcode, cls, ref2oper(ins->l), ref2oper(ins->r)); + else /* CMP ... ==> SUBS zr, ... */ Xsubs(pcode, cls, REGZR, ref2oper(ins->l), ref2oper(ins->r)); + lastcmp = ins; + if (ins->reg) { + enum cc cc = (kisflt(cls) ? fcmpop2cc : icmpop2cc)[ins->op]; + dst = reg2oper(ins->reg-1); + assert(dst.reg < R(31)); + W32(0x1A9F07E0 | (cc^1)<<12 | dst.reg); /* CSET Wd, */ + } break; case Oloadu8: X2 = Xldrb; goto Load; case Oloads8: X2 = Xldrsb; goto Load; @@ -887,6 +907,7 @@ emitbin(struct function *fn) bb->resolved = 1; bb->addr = bbaddr; + lastcmp = NULL; for (int i = 0; i < blk->ins.n; ++i) emitinstr(pcode, fn, blk, i, &instrtab[blk->ins.p[i]]); if (blk->jmp.t == Jret) { diff --git a/obj/elf.c b/obj/elf.c index 8c63295..5044e56 100644 --- a/obj/elf.c +++ b/obj/elf.c @@ -151,9 +151,11 @@ static const ushort relktab[][NRELOCKIND] = { [REL_PCREL32] = 261, /* R_AARCH64_PREL2 */ [REL_PLT32] = 314, /* R_AARCH64_PLT32 */ [REL_CALL26] = 283, /* R_AARCH64_CALL26 */ + [REL_LD_PREL_LO19] = 273, /* R_AARCH64_LD_PREL_LO19 */ [REL_ADR_PREL_LO21] = 274, /* R_AARCH64_ADR_PREL_LO21 */ [REL_ADR_PREL_PG_HI21] = 276, /* R_AARCH64_ADR_PREL_PG_HI21_NC */ [REL_ADD_ABS_LO12_NC] = 277, /* R_AARCH64_ADD_ABS_LO12_NC */ + } }; diff --git a/obj/obj.h b/obj/obj.h index 0b2eb6c..1982033 100644 --- a/obj/obj.h +++ b/obj/obj.h @@ -21,6 +21,7 @@ enum relockind { REL_ADR_PREL_LO21, REL_ADR_PREL_PG_HI21, REL_ADD_ABS_LO12_NC, + REL_LD_PREL_LO19, NRELOCKIND, }; enum section { Snone, Stext, Srodata, Sdata, Sbss }; -- cgit v1.2.3