summaryrefslogtreecommitdiff
path: root/utils/5c/txt.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/5c/txt.c')
-rw-r--r--utils/5c/txt.c87
1 files changed, 70 insertions, 17 deletions
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;
}