arm64: prevent bogus IP1 clobbers

This commit is contained in:
Quentin Carbonneaux 2026-01-06 19:35:14 +01:00
parent 03da40271f
commit 73f0accb45

View File

@ -109,6 +109,10 @@ static struct {
{ NOp, 0, 0 } { NOp, 0, 0 }
}; };
enum {
V31 = 0x1fffffff, /* local name for V31 */
};
static char * static char *
rname(int r, int k) rname(int r, int k)
{ {
@ -132,6 +136,12 @@ rname(int r, int k)
case Kx: case Kx:
case Kd: sprintf(buf, "d%d", r-V0); break; case Kd: sprintf(buf, "d%d", r-V0); break;
} }
else if (r == V31)
switch (k) {
default: die("invalid class");
case Ks: sprintf(buf, "s31"); break;
case Kd: sprintf(buf, "d31"); break;
}
else else
die("invalid register"); die("invalid register");
return buf; return buf;
@ -172,7 +182,7 @@ emitf(char *s, Ins *i, E *e)
if (c == ' ' && !sp) { if (c == ' ' && !sp) {
fputc('\t', e->f); fputc('\t', e->f);
sp = 1; sp = 1;
} else if ( !c) { } else if (!c) {
fputc('\n', e->f); fputc('\n', e->f);
return; return;
} else } else
@ -197,12 +207,12 @@ emitf(char *s, Ins *i, E *e)
if (KBASE(k) == 0) if (KBASE(k) == 0)
fputs(rname(IP1, k), e->f); fputs(rname(IP1, k), e->f);
else else
fputs(k==Ks ? "s31" : "d31", e->f); fputs(rname(V31, k), e->f);
break; break;
case '=': case '=':
case '0': case '0':
r = c == '=' ? i->to : i->arg[0]; r = c == '=' ? i->to : i->arg[0];
assert(isreg(r)); assert(isreg(r) || req(r, TMP(V31)));
fputs(rname(r.val, k), e->f); fputs(rname(r.val, k), e->f);
break; break;
case '1': case '1':
@ -335,8 +345,8 @@ loadcon(Con *c, int r, int k, E *e)
static void emitins(Ins *, E *); static void emitins(Ins *, E *);
static void static int
fixarg(Ref *pr, int sz, E *e) fixarg(Ref *pr, int sz, int t, E *e)
{ {
Ins *i; Ins *i;
Ref r; Ref r;
@ -346,11 +356,14 @@ fixarg(Ref *pr, int sz, E *e)
if (rtype(r) == RSlot) { if (rtype(r) == RSlot) {
s = slot(r, e); s = slot(r, e);
if (s > sz * 4095u) { if (s > sz * 4095u) {
i = &(Ins){Oaddr, Kl, TMP(IP1), {r}}; if (t < 0)
return 1;
i = &(Ins){Oaddr, Kl, TMP(t), {r}};
emitins(i, e); emitins(i, e);
*pr = TMP(IP1); *pr = TMP(t);
} }
} }
return 0;
} }
static void static void
@ -358,16 +371,28 @@ emitins(Ins *i, E *e)
{ {
char *l, *p, *rn; char *l, *p, *rn;
uint64_t s; uint64_t s;
int o; int o, t;
Ref r; Ref r;
Con *c; Con *c;
switch (i->op) { switch (i->op) {
default: default:
if (isload(i->op)) if (isload(i->op))
fixarg(&i->arg[0], loadsz(i), e); fixarg(&i->arg[0], loadsz(i), IP1, e);
if (isstore(i->op)) if (isstore(i->op)) {
fixarg(&i->arg[1], storesz(i), e); t = T.apple ? -1 : R18;
if (fixarg(&i->arg[1], storesz(i), t, e)) {
if (req(i->arg[0], TMP(IP1))) {
fprintf(e->f,
"\tfmov\t%c31, %c17\n",
"ds"[i->cls == Kw],
"xw"[i->cls == Kw]);
i->arg[0] = TMP(V31);
i->op = Ostores + (i->cls-Kw);
}
fixarg(&i->arg[1], storesz(i), IP1, e);
}
}
Table: Table:
/* most instructions are just pulled out of /* most instructions are just pulled out of
* the table omap[], some special cases are * the table omap[], some special cases are