summaryrefslogtreecommitdiff
path: root/utils/5c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/5c')
-rw-r--r--utils/5c/5.out.h16
-rw-r--r--utils/5c/enam.c6
-rw-r--r--utils/5c/gc.h11
-rw-r--r--utils/5c/list.c2
-rw-r--r--utils/5c/peep.c5
-rw-r--r--utils/5c/reg.c4
-rw-r--r--utils/5c/swt.c39
-rw-r--r--utils/5c/txt.c87
8 files changed, 112 insertions, 58 deletions
diff --git a/utils/5c/5.out.h b/utils/5c/5.out.h
index dad2c336..a618f8f1 100644
--- a/utils/5c/5.out.h
+++ b/utils/5c/5.out.h
@@ -25,6 +25,7 @@
#define NFREG 8
#define FREGRET 0
#define FREGEXT 7
+#define FREGTMP 15
/* compiler allocates register variables F0 up */
/* compiler allocates external registers F7 down */
@@ -92,6 +93,8 @@ enum as
AMULD,
ADIVF,
ADIVD,
+// ASQRTF,
+// ASQRTD,
ASRL,
ASRA,
@@ -143,6 +146,16 @@ enum as
ASIGNAME,
+ /* moved here to preserve values of older identifiers */
+ ASQRTF,
+ ASQRTD,
+
+ ALDREX,
+ ASTREX,
+
+ ALDREXD,
+ ASTREXD,
+
ALAST,
};
@@ -173,7 +186,8 @@ enum as
#define D_SHIFT (D_NONE+19)
#define D_FPCR (D_NONE+20)
-#define D_REGREG (D_NONE+21)
+#define D_REGREG (D_NONE+21)
+#define D_ADDR (D_NONE+22)
/* name */
#define D_EXTERN (D_NONE+3)
diff --git a/utils/5c/enam.c b/utils/5c/enam.c
index 989b2760..e5ea0b84 100644
--- a/utils/5c/enam.c
+++ b/utils/5c/enam.c
@@ -94,5 +94,11 @@ char* anames[] =
"BXRET",
"DWORD",
"SIGNAME",
+ "SQRTF",
+ "SQRTD",
+ "LDREX",
+ "STREX",
+ "LDREXD",
+ "STREXD",
"LAST",
};
diff --git a/utils/5c/gc.h b/utils/5c/gc.h
index fa93cd0a..b9382a00 100644
--- a/utils/5c/gc.h
+++ b/utils/5c/gc.h
@@ -3,7 +3,7 @@
/*
* 5c/arm
- * Arm 7500
+ * Arm
*/
#define SZ_CHAR 1
#define SZ_SHORT 2
@@ -59,7 +59,7 @@ struct Prog
struct Case
{
Case* link;
- long val;
+ vlong val;
long label;
char def;
char isv;
@@ -68,7 +68,7 @@ struct Case
struct C1
{
- long val;
+ vlong val;
long label;
};
@@ -265,7 +265,7 @@ void gpseudo(int, Sym*, Node*);
/*
* swt.c
*/
-int swcmp(const void*, const void*);
+int swcmp(void*, void*);
void doswit(Node*);
void swit1(C1*, int, long, Node*);
void swit2(C1*, int, long, Node*, Node*);
@@ -276,7 +276,6 @@ long outstring(char*, long);
int mulcon(Node*, Node*);
Multab* mulcon0(long);
void nullwarn(Node*, Node*);
-void sextern(Sym*, Node*, long, long);
void gextern(Sym*, Node*, long, long);
void outcode(void);
void ieeedtod(Ieee*, double);
@@ -297,7 +296,7 @@ int Rconv(Fmt*);
* reg.c
*/
Reg* rega(void);
-int rcmp(const void*, const void*);
+int rcmp(void*, void*);
void regopt(Prog*);
void addmove(Reg*, int, int, int);
Bits mkvar(Adr*, int);
diff --git a/utils/5c/list.c b/utils/5c/list.c
index d50f07db..c7276dd8 100644
--- a/utils/5c/list.c
+++ b/utils/5c/list.c
@@ -98,7 +98,7 @@ Aconv(Fmt *fp)
int a;
a = va_arg(fp->args, int);
- s = "???";
+ s = "?";
if(a >= AXXX && a < ALAST)
s = anames[a];
return fmtstrcpy(fp, s);
diff --git a/utils/5c/peep.c b/utils/5c/peep.c
index 25e5a118..9d4a2da2 100644
--- a/utils/5c/peep.c
+++ b/utils/5c/peep.c
@@ -1069,7 +1069,7 @@ copyu(Prog *p, Adr *v, Adr *s)
if(v->type == D_REG) {
if(v->reg <= REGEXT && v->reg > exregoffset)
return 2;
- if(v->reg == REGARG)
+ if(v->reg == (uchar)REGARG)
return 2;
}
if(v->type == D_FREG)
@@ -1087,11 +1087,10 @@ copyu(Prog *p, Adr *v, Adr *s)
case ATEXT: /* funny */
if(v->type == D_REG)
- if(v->reg == REGARG)
+ if(v->reg == (uchar)REGARG)
return 3;
return 0;
}
- /* not reached */
}
int
diff --git a/utils/5c/reg.c b/utils/5c/reg.c
index 43c78712..ab1005ba 100644
--- a/utils/5c/reg.c
+++ b/utils/5c/reg.c
@@ -18,7 +18,7 @@ rega(void)
}
int
-rcmp(const void *a1, const void *a2)
+rcmp(void *a1, void *a2)
{
Rgn *p1, *p2;
int c1, c2;
@@ -1125,7 +1125,7 @@ RtoB(int r)
int
BtoR(long b)
{
- b &= 0x01fcL;
+ b &= 0x01fcL; // excluded R9 and R10 for extern registers
if(b == 0)
return 0;
return bitno(b);
diff --git a/utils/5c/swt.c b/utils/5c/swt.c
index ccc63ee7..6e0b8d51 100644
--- a/utils/5c/swt.c
+++ b/utils/5c/swt.c
@@ -25,8 +25,8 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
}
if(nc < 5) {
for(i=0; i<nc; i++) {
- if(debug['W'])
- print("case = %.8lux\n", q->val);
+ if(debug['K'])
+ print("case = %.8llux\n", q->val);
gopcode(OEQ, nodconst(q->val), n, Z);
patch(p, q->label);
q++;
@@ -38,16 +38,16 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
i = nc / 2;
r = q+i;
- if(debug['W'])
- print("case > %.8lux\n", r->val);
+ if(debug['K'])
+ print("case > %.8llux\n", r->val);
gopcode(OGT, nodconst(r->val), n, Z);
sp = p;
gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */
patch(p, r->label);
swit2(q, i, def, n, tn);
- if(debug['W'])
- print("case < %.8lux\n", r->val);
+ if(debug['K'])
+ print("case < %.8llux\n", r->val);
patch(sp, pc);
swit2(r+1, nc-i-1, def, n, tn);
return;
@@ -59,8 +59,8 @@ direct:
gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z);
patch(p, def);
for(i=0; i<nc; i++) {
- if(debug['W'])
- print("case = %.8lux\n", q->val);
+ if(debug['K'])
+ print("case = %.8llux\n", q->val);
while(q->val != v) {
nextpc();
p->as = ABCASE;
@@ -269,23 +269,6 @@ loop:
}
void
-sextern(Sym *s, Node *a, long o, long w)
-{
- long e, lw;
-
- for(e=0; e<w; e+=NSNAME) {
- lw = NSNAME;
- if(w-e < lw)
- lw = w-e;
- gpseudo(ADATA, s, nodconst(0));
- p->from.offset += o+e;
- p->reg = lw;
- p->to.type = D_SCONST;
- memmove(p->to.sval, a->cstring+e, lw);
- }
-}
-
-void
gextern(Sym *s, Node *a, long o, long w)
{
@@ -579,7 +562,7 @@ align(long i, Type *t, int op)
w = packflg;
break;
- case Ael1: /* initial allign of struct element */
+ case Ael1: /* initial align of struct element */
for(v=t; v->etype==TARRAY; v=v->link)
;
w = ewidth[v->etype];
@@ -600,7 +583,7 @@ align(long i, Type *t, int op)
}
break;
- case Aarg1: /* initial allign of parameter */
+ case Aarg1: /* initial align of parameter */
w = ewidth[t->etype];
if(w <= 0 || w >= SZ_LONG) {
w = SZ_LONG;
@@ -614,7 +597,7 @@ align(long i, Type *t, int op)
w = SZ_LONG;
break;
- case Aaut3: /* total allign of automatic */
+ case Aaut3: /* total align of automatic */
o = align(o, t, Ael2);
o = align(o, t, Ael1);
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
diff --git a/utils/5c/txt.c b/utils/5c/txt.c
index f97eb61a..fadf5938 100644
--- a/utils/5c/txt.c
+++ b/utils/5c/txt.c
@@ -1,5 +1,7 @@
#include "gc.h"
+static char resvreg[nelem(reg)];
+
void
ginit(void)
{
@@ -80,6 +82,16 @@ ginit(void)
com64init();
memset(reg, 0, sizeof(reg));
+ /* don't allocate */
+ reg[REGTMP] = 1;
+ reg[REGSB] = 1;
+ reg[REGSP] = 1;
+ reg[REGLINK] = 1;
+ reg[REGPC] = 1;
+ /* keep two external registers */
+ reg[REGEXT] = 1;
+ reg[REGEXT-1] = 1;
+ memmove(resvreg, reg, sizeof(reg));
}
void
@@ -89,10 +101,10 @@ gclean(void)
Sym *s;
for(i=0; i<NREG; i++)
- if(reg[i])
+ if(reg[i] && !resvreg[i])
diag(Z, "reg %d left allocated", i);
for(i=NREG; i<NREG+NFREG; i++)
- if(reg[i])
+ if(reg[i] && !resvreg[i])
diag(Z, "freg %d left allocated", i-NREG);
while(mnstring)
outstring("", 1L);
@@ -283,7 +295,7 @@ regalloc(Node *n, Node *tn, Node *o)
for(i=REGRET+1; i<NREG; i++) {
if(j >= NREG)
j = REGRET+1;
- if(reg[j] == 0) {
+ if(reg[j] == 0 && resvreg[j] == 0) {
i = j;
goto out;
}
@@ -319,7 +331,7 @@ err:
return;
out:
reg[i]++;
-/* lasti++; *** StrongARM does register forwarding */
+ lasti++;
if(lasti >= 5)
lasti = 0;
nodreg(n, tn, i);
@@ -549,7 +561,8 @@ void
gmove(Node *f, Node *t)
{
int ft, tt, a;
- Node nod;
+ Node nod, nod1;
+ Prog *p1;
ft = f->type->etype;
tt = t->type->etype;
@@ -678,21 +691,58 @@ gmove(Node *f, Node *t)
}
break;
case TUINT:
- case TINT:
case TULONG:
+ if(tt == TFLOAT || tt == TDOUBLE) {
+ // ugly and probably longer than necessary,
+ // but vfp has a single instruction for this,
+ // so hopefully it won't last long.
+ //
+ // tmp = f
+ // tmp1 = tmp & 0x80000000
+ // tmp ^= tmp1
+ // t = float(int32(tmp))
+ // if(tmp1)
+ // t += 2147483648.
+ //
+ regalloc(&nod, f, Z);
+ regalloc(&nod1, f, Z);
+ gins(AMOVW, f, &nod);
+ gins(AMOVW, &nod, &nod1);
+ gins(AAND, nodconst(0x80000000), &nod1);
+ gins(AEOR, &nod1, &nod);
+ if(tt == TFLOAT)
+ gins(AMOVWF, &nod, t);
+ else
+ gins(AMOVWD, &nod, t);
+ gins(ACMP, nodconst(0), Z);
+ raddr(&nod1, p);
+ gins(ABEQ, Z, Z);
+ regfree(&nod);
+ regfree(&nod1);
+ p1 = p;
+ regalloc(&nod, t, Z);
+ if(tt == TFLOAT) {
+ gins(AMOVF, nodfconst(2147483648.), &nod);
+ gins(AADDF, &nod, t);
+ } else {
+ gins(AMOVD, nodfconst(2147483648.), &nod);
+ gins(AADDD, &nod, t);
+ }
+ regfree(&nod);
+ patch(p1, pc);
+ return;
+ }
+ // fall through
+
+ case TINT:
case TLONG:
case TIND:
switch(tt) {
case TDOUBLE:
- case TVLONG:
gins(AMOVWD, f, t);
- if(ft == TULONG) {
- }
return;
case TFLOAT:
gins(AMOVWF, f, t);
- if(ft == TULONG) {
- }
return;
case TINT:
case TUINT:
@@ -710,7 +760,6 @@ gmove(Node *f, Node *t)
case TSHORT:
switch(tt) {
case TDOUBLE:
- case TVLONG:
regalloc(&nod, f, Z);
gins(AMOVH, f, &nod);
gins(AMOVWD, &nod, t);
@@ -740,7 +789,6 @@ gmove(Node *f, Node *t)
case TUSHORT:
switch(tt) {
case TDOUBLE:
- case TVLONG:
regalloc(&nod, f, Z);
gins(AMOVHU, f, &nod);
gins(AMOVWD, &nod, t);
@@ -770,7 +818,6 @@ gmove(Node *f, Node *t)
case TCHAR:
switch(tt) {
case TDOUBLE:
- case TVLONG:
regalloc(&nod, f, Z);
gins(AMOVB, f, &nod);
gins(AMOVWD, &nod, t);
@@ -800,7 +847,6 @@ gmove(Node *f, Node *t)
case TUCHAR:
switch(tt) {
case TDOUBLE:
- case TVLONG:
regalloc(&nod, f, Z);
gins(AMOVBU, f, &nod);
gins(AMOVWD, &nod, t);
@@ -1015,7 +1061,8 @@ gopcode(int o, Node *f1, Node *f2, Node *t)
nextpc();
p->as = a;
naddr(f1, &p->from);
- if(a == ACMP && f1->op == OCONST && p->from.offset < 0) {
+ if(a == ACMP && f1->op == OCONST && p->from.offset < 0 &&
+ p->from.offset != 0x80000000) {
p->as = ACMN;
p->from.offset = -p->from.offset;
}
@@ -1185,9 +1232,12 @@ exreg(Type *t)
long o;
if(typechlp[t->etype]) {
- if(exregoffset <= REGEXT-4)
+ if(exregoffset <= REGEXT-2)
return 0;
o = exregoffset;
+ if(reg[o] && !resvreg[o])
+ return 0;
+ resvreg[o] = reg[o] = 1;
exregoffset--;
return o;
}
@@ -1195,6 +1245,9 @@ exreg(Type *t)
if(exfregoffset <= NFREG-1)
return 0;
o = exfregoffset + NREG;
+ if(reg[o] && !resvreg[o])
+ return 0;
+ resvreg[o] = reg[o] = 1;
exfregoffset--;
return o;
}