aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-01-07 10:32:18 +0100
committerlemon <lsof@mailbox.org>2026-01-07 10:32:18 +0100
commitc7e34f7e4ae6854b82f345f07589a646cf8376cf (patch)
treefb7ec721f8c5d81b64d23f006e22295d4bfc0b1d
parent1f074a44bcfade5b538c24e202d6d2869abfb0ac (diff)
aarch64: vshifts, flt cvt
-rw-r--r--aarch64/emit.c57
-rw-r--r--aarch64/isel.c16
2 files changed, 67 insertions, 6 deletions
diff --git a/aarch64/emit.c b/aarch64/emit.c
index 8fe3677..e470813 100644
--- a/aarch64/emit.c
+++ b/aarch64/emit.c
@@ -367,6 +367,9 @@ DEFINSTR3(Xeor,
{4|8, {PGPRSP, PGPRZ, PLOGIMM}, 0x52000000, EN_LOGIMM}, /* EOR (immediate) */
{4|8, {PGPRZ, PGPRZ, PGPRZSHFT}, 0x4A000000, EN_LOGSHFT3R}, /* EOR (shifted register) */
)
+DEFINSTR3(Xlslv, {4|8, {PGPRZ, PGPRZ, PGPRZ}, 0x1AC02000, EN_ARITH3R})
+DEFINSTR3(Xlsrv, {4|8, {PGPRZ, PGPRZ, PGPRZ}, 0x1AC02400, EN_ARITH3R})
+DEFINSTR3(Xasrv, {4|8, {PGPRZ, PGPRZ, PGPRZ}, 0x1AC02800, EN_ARITH3R})
static void
Xubfm(uchar **pcode, enum irclass k, struct oper rd, struct oper rn, uint immr, uint imms)
{
@@ -487,6 +490,16 @@ DEFINSTR2(Xfmov,
{ 8, {PGPRZ, PFPR}, 0x9E660000, EN_FP1GPR1},
)
DEFINSTR2(Xfneg, {4|8, {PFPR, PFPR}, 0x1E214000, EN_FP2R})
+DEFINSTR2(Xscvtfw, {4|8, {PFPR, PGPRZ}, 0x1E220000, EN_FP2R})
+DEFINSTR2(Xscvtfx, {4|8, {PFPR, PGPRZ}, 0x9E220000, EN_FP2R})
+DEFINSTR2(Xfcvtzsw, {4|8, {PGPRZ, PFPR}, 0x1E380000, EN_FP2R})
+DEFINSTR2(Xfcvtzsx, {4|8, {PGPRZ, PFPR}, 0x9E380000, EN_FP2R})
+DEFINSTR2(Xucvtfw, {4|8, {PFPR, PGPRZ}, 0x1E230000, EN_FP2R})
+DEFINSTR2(Xucvtfx, {4|8, {PFPR, PGPRZ}, 0x9E230000, EN_FP2R})
+DEFINSTR2(Xfcvtzuw, {4|8, {PGPRZ, PFPR}, 0x1E390000, EN_FP2R})
+DEFINSTR2(Xfcvtzux, {4|8, {PGPRZ, PFPR}, 0x9E390000, EN_FP2R})
+DEFINSTR2(Xfcvtds, {4, {PFPR, PFPR}, 0x1E624000, EN_FP2R})
+DEFINSTR2(Xfcvtsd, {4, {PFPR, PFPR}, 0x1E22C000, EN_FP2R})
DEFINSTR3(Xfadd, {4|8, {PFPR, PFPR, PFPR}, 0x1E202800, EN_FP3R})
DEFINSTR3(Xfsub, {4|8, {PFPR, PFPR, PFPR}, 0x1E203800, EN_FP3R})
DEFINSTR3(Xfmul, {4|8, {PFPR, PFPR, PFPR}, 0x1E200800, EN_FP3R})
@@ -699,6 +712,31 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
case Oextu8: case Oextu16: /* UXTB/H Rd, Rn ==> UBFM Rd, Rn, #0, #7/15 */
Xubfm(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), 0, (8<<(ins->op-Oexts8)/2)-1);
break;
+ case Ocvts32f: X2 = Xscvtfw; goto Cvt;
+ case Ocvts64f: X2 = Xscvtfx; goto Cvt;
+ case Ocvtf32s:
+ X2 = cls == KI32 ? Xfcvtzsw : Xfcvtzsx;
+ cls = KF32;
+ goto Cvt;
+ case Ocvtf64s:
+ X2 = cls == KI32 ? Xfcvtzsw : Xfcvtzsx;
+ cls = KF64;
+ goto Cvt;
+ case Ocvtu32f: X2 = Xucvtfw; goto Cvt;
+ case Ocvtu64f: X2 = Xucvtfx; goto Cvt;
+ case Ocvtf32u:
+ X2 = cls == KI32 ? Xfcvtzuw : Xfcvtzux;
+ cls = KF32;
+ goto Cvt;
+ case Ocvtf64u:
+ X2 = cls == KI32 ? Xfcvtzuw : Xfcvtzux;
+ cls = KF64;
+ goto Cvt;
+ case Ocvtf32f64: cls = KF32; X2 = Xfcvtsd; goto Cvt;
+ case Ocvtf64f32: cls = KF32; X2 = Xfcvtds; goto Cvt;
+ Cvt:
+ X2(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; }
@@ -718,24 +756,34 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
uint nbit = cls == KI32 ? 32 : 64, s = ins->r.i & nbit-1;
assert(s > 0);
Xubfm(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), nbit-s, nbit-s-1);
- } else assert(!"nyi lslv");
+ } else {
+ X3 = Xlslv;
+ goto ALU3;
+ }
break;
case Oslr:
if (ins->r.t == RICON) {
uint nbit = cls == KI32 ? 32 : 64, s = ins->r.i & nbit-1;
assert(s > 0);
Xubfm(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), s, nbit-1);
- } else assert(!"nyi lsrv");
+ } else {
+ X3 = Xlsrv;
+ goto ALU3;
+ }
break;
case Osar:
if (ins->r.t == RICON) {
uint nbit = cls == KI32 ? 32 : 64, s = ins->r.i & nbit-1;
assert(s > 0);
Xsbfm(pcode, cls, reg2oper(ins->reg-1), ref2oper(ins->l), s, nbit-1);
- } else assert(!"nyi lsrv");
+ } else {
+ X3 = Xasrv;
+ goto ALU3;
+ }
break;
case Oequ: case Oneq:
- if (!ins->reg && kisint(cls) && ins->r.bits == ZEROREF.bits) break; /* handled by emitbranch for CBZ/CBNZ */
+ if (!ins->reg && kisint(cls) && ins->r.bits == ZEROREF.bits) /* handled by emitbranch for CBZ/CBNZ */
+ break;
case Olth: case Ogth: case Olte: case Ogte:
case Oulth: case Ougth: case Oulte: case Ougte:
if (lastcmp && lastcmp->cls == cls
@@ -762,7 +810,6 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
X2 = Xldrsw;
goto Load;
}
- /* fallthru */
case Oloadu32:
cls = KI32;
/* fallthru */
diff --git a/aarch64/isel.c b/aarch64/isel.c
index 65e61cf..5433add 100644
--- a/aarch64/isel.c
+++ b/aarch64/isel.c
@@ -109,7 +109,21 @@ fixarg(union ref *r, struct instr *ins, struct block *blk, int *curi)
} else if (isfltcon(*r)) {
enum irclass k = concls(*r), ki = KI32 + k-KF32;
if (conht[r->i].f != 0.0) {
- union ref gpr = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ki, mkintcon(ki, conht[r->i].i)));
+ union {
+ vlong i64;
+ int i32;
+ float f32;
+ double f64;
+ } pun;
+ vlong i;
+ if (k == KF32) {
+ pun.f32 = conht[r->i].f;
+ i = pun.i32;
+ } else {
+ pun.f64 = conht[r->i].f;
+ i = pun.i64;
+ }
+ union ref gpr = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ki, mkintcon(ki, i)));
*r = insertinstr(blk, (*curi)++, mkinstr(Ocopy, k, gpr));
} else if (oiscmp(op)) {
return;