summaryrefslogtreecommitdiff
path: root/src/cmd/5g/reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g/reg.c')
-rw-r--r--src/cmd/5g/reg.c184
1 files changed, 172 insertions, 12 deletions
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 1cbeb3e3d..5fba02c9e 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -32,6 +32,8 @@
#include "gg.h"
#include "opt.h"
+#define NREGVAR 24
+#define REGBITS ((uint32)0xffffff)
#define P2R(p) (Reg*)(p->reg)
void addsplits(void);
@@ -128,6 +130,33 @@ setaddrs(Bits bit)
}
}
+static char* regname[] = {
+ ".R0",
+ ".R1",
+ ".R2",
+ ".R3",
+ ".R4",
+ ".R5",
+ ".R6",
+ ".R7",
+ ".R8",
+ ".R9",
+ ".R10",
+ ".R11",
+ ".R12",
+ ".R13",
+ ".R14",
+ ".R15",
+ ".F0",
+ ".F1",
+ ".F2",
+ ".F3",
+ ".F4",
+ ".F5",
+ ".F6",
+ ".F7",
+};
+
void
regopt(Prog *firstp)
{
@@ -136,7 +165,7 @@ regopt(Prog *firstp)
int i, z, nr;
uint32 vreg;
Bits bit;
-
+
if(first == 0) {
fmtinstall('Q', Qconv);
}
@@ -164,7 +193,17 @@ regopt(Prog *firstp)
r1 = R;
firstr = R;
lastr = R;
- nvar = 0;
+
+ /*
+ * control flow is more complicated in generated go code
+ * than in generated c code. define pseudo-variables for
+ * registers, so we have complete register usage information.
+ */
+ nvar = NREGVAR;
+ memset(var, 0, NREGVAR*sizeof var[0]);
+ for(i=0; i<NREGVAR; i++)
+ var[i].sym = lookup(regname[i]);
+
regbits = RtoB(REGSP)|RtoB(REGLINK)|RtoB(REGPC);
for(z=0; z<BITS; z++) {
externs.b[z] = 0;
@@ -223,6 +262,16 @@ regopt(Prog *firstp)
bit = mkvar(r, &p->from);
for(z=0; z<BITS; z++)
r->use1.b[z] |= bit.b[z];
+
+ /*
+ * middle always read when present
+ */
+ if(p->reg != NREG) {
+ if(p->from.type != D_FREG)
+ r->use1.b[0] |= RtoB(p->reg);
+ else
+ r->use1.b[0] |= FtoB(p->reg);
+ }
/*
* right side depends on opcode
@@ -233,6 +282,67 @@ regopt(Prog *firstp)
default:
yyerror("reg: unknown op: %A", p->as);
break;
+
+ /*
+ * right side read
+ */
+ case ATST:
+ case ATEQ:
+ case ACMP:
+ case ACMN:
+ case ACMPD:
+ case ACMPF:
+ rightread:
+ for(z=0; z<BITS; z++)
+ r->use2.b[z] |= bit.b[z];
+ break;
+
+ /*
+ * right side read or read+write, depending on middle
+ * ADD x, z => z += x
+ * ADD x, y, z => z = x + y
+ */
+ case AADD:
+ case AAND:
+ case AEOR:
+ case ASUB:
+ case ARSB:
+ case AADC:
+ case ASBC:
+ case ARSC:
+ case AORR:
+ case ABIC:
+ case ASLL:
+ case ASRL:
+ case ASRA:
+ case AMUL:
+ case AMULU:
+ case ADIV:
+ case AMOD:
+ case AMODU:
+ case ADIVU:
+ if(p->reg != NREG)
+ goto rightread;
+ // fall through
+
+ /*
+ * right side read+write
+ */
+ case AADDF:
+ case AADDD:
+ case ASUBF:
+ case ASUBD:
+ case AMULF:
+ case AMULD:
+ case ADIVF:
+ case ADIVD:
+ case AMULAL:
+ case AMULALU:
+ for(z=0; z<BITS; z++) {
+ r->use2.b[z] |= bit.b[z];
+ r->set.b[z] |= bit.b[z];
+ }
+ break;
/*
* right side write
@@ -240,11 +350,22 @@ regopt(Prog *firstp)
case ANOP:
case AMOVB:
case AMOVBU:
+ case AMOVD:
+ case AMOVDF:
+ case AMOVDW:
+ case AMOVF:
+ case AMOVFW:
case AMOVH:
case AMOVHU:
case AMOVW:
- case AMOVF:
- case AMOVD:
+ case AMOVWD:
+ case AMOVWF:
+ case AMVN:
+ case AMULL:
+ case AMULLU:
+ if((p->scond & C_SCOND) != C_SCOND_NONE)
+ for(z=0; z<BITS; z++)
+ r->use2.b[z] |= bit.b[z];
for(z=0; z<BITS; z++)
r->set.b[z] |= bit.b[z];
break;
@@ -397,6 +518,24 @@ loop2:
}
/*
+ * pass 4.5
+ * move register pseudo-variables into regu.
+ */
+ for(r = firstr; r != R; r = r->link) {
+ r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS;
+
+ r->set.b[0] &= ~REGBITS;
+ r->use1.b[0] &= ~REGBITS;
+ r->use2.b[0] &= ~REGBITS;
+ r->refbehind.b[0] &= ~REGBITS;
+ r->refahead.b[0] &= ~REGBITS;
+ r->calbehind.b[0] &= ~REGBITS;
+ r->calahead.b[0] &= ~REGBITS;
+ r->regdiff.b[0] &= ~REGBITS;
+ r->act.b[0] &= ~REGBITS;
+ }
+
+ /*
* pass 5
* isolate regions
* calculate costs (paint1)
@@ -606,6 +745,7 @@ addmove(Reg *r, int bn, int rn, int f)
a = &p1->to;
a->sym = v->sym;
a->name = v->name;
+ a->node = v->node;
a->offset = v->offset;
a->etype = v->etype;
a->type = D_OREG;
@@ -715,21 +855,40 @@ mkvar(Reg *r, Adr *a)
goto onereg;
case D_REGREG:
+ bit = zbits;
if(a->offset != NREG)
- r->regu |= RtoB(a->offset);
- goto onereg;
+ bit.b[0] |= RtoB(a->offset);
+ if(a->reg != NREG)
+ bit.b[0] |= RtoB(a->reg);
+ return bit;
case D_REG:
case D_SHIFT:
- case D_OREG:
onereg:
- if(a->reg != NREG)
- r->regu |= RtoB(a->reg);
+ if(a->reg != NREG) {
+ bit = zbits;
+ bit.b[0] = RtoB(a->reg);
+ return bit;
+ }
+ break;
+
+ case D_OREG:
+ if(a->reg != NREG) {
+ if(a == &r->prog->from)
+ r->use1.b[0] |= RtoB(a->reg);
+ else
+ r->use2.b[0] |= RtoB(a->reg);
+ if(r->prog->scond & (C_PBIT|C_WBIT))
+ r->set.b[0] |= RtoB(a->reg);
+ }
break;
case D_FREG:
- if(a->reg != NREG)
- r->regu |= FtoB(a->reg);
+ if(a->reg != NREG) {
+ bit = zbits;
+ bit.b[0] = FtoB(a->reg);
+ return bit;
+ }
break;
}
@@ -795,7 +954,8 @@ mkvar(Reg *r, Adr *a)
v->etype = et;
v->width = w;
v->addr = flag; // funny punning
-
+ v->node = a->node;
+
if(debug['R'])
print("bit=%2d et=%E pun=%d %D\n", i, et, flag, a);