mirror of
https://github.com/golang/go
synced 2024-10-06 08:00:07 +00:00
[dev.garbage] all: merge dev.power64 (7667e41f3ced) into dev.garbage
Now the only difference between dev.cc and dev.garbage is the runtime conversion on the one side and the garbage collection on the other. They both have the same set of changes from default and dev.power64. LGTM=austin R=austin CC=golang-codereviews https://golang.org/cl/172570043
This commit is contained in:
commit
9ef4e56108
|
@ -54,7 +54,7 @@ struct Addr
|
|||
{
|
||||
char sval[8];
|
||||
float64 dval;
|
||||
Prog* branch; // for 5g, 6g, 8g
|
||||
Prog* branch; // for 5g, 6g, 8g, 9g
|
||||
} u;
|
||||
|
||||
LSym* sym;
|
||||
|
@ -89,10 +89,13 @@ struct Prog
|
|||
int32 lineno;
|
||||
Prog* link;
|
||||
short as;
|
||||
uchar reg; // arm, power64 only
|
||||
uchar scond; // arm only
|
||||
|
||||
// operands
|
||||
Addr from;
|
||||
Addr from3; // power64 only, fma and rlwm
|
||||
uchar reg; // arm, power64 only (e.g., ADD from, reg, to);
|
||||
// also used for ADATA width on arm, power64
|
||||
Addr from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to)
|
||||
Addr to;
|
||||
|
||||
// for 5g, 6g, 8g internal use
|
||||
|
|
|
@ -86,7 +86,7 @@ datagostring(Strlit *sval, Addr *a)
|
|||
sym = stringsym(sval->s, sval->len);
|
||||
a->type = D_OREG;
|
||||
a->name = D_EXTERN;
|
||||
a->etype = TINT32;
|
||||
a->etype = TSTRING;
|
||||
a->offset = 0; // header
|
||||
a->reg = NREG;
|
||||
a->sym = linksym(sym);
|
||||
|
|
|
@ -1353,9 +1353,10 @@ naddr(Node *n, Addr *a, int canemitcode)
|
|||
case OITAB:
|
||||
// itable of interface value
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->etype = TINT32;
|
||||
a->etype = simtype[tptr];
|
||||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // len(nil)
|
||||
a->width = widthptr;
|
||||
break;
|
||||
|
||||
case OSPTR:
|
||||
|
|
|
@ -63,8 +63,8 @@ enum
|
|||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint32 LOAD(Reg*);
|
||||
uint32 STORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
|
@ -145,7 +145,7 @@ void synch(Reg*, Bits);
|
|||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpit(char *str, Flow *r0, int);
|
||||
|
||||
|
@ -156,10 +156,10 @@ void peep(Prog*);
|
|||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "opt.h"
|
||||
|
||||
#define NREGVAR 32
|
||||
#define REGBITS ((uint32)0xffffffff)
|
||||
#define REGBITS ((uint64)0xffffffffull)
|
||||
/*c2go enum {
|
||||
NREGVAR = 32,
|
||||
REGBITS = 0xffffffff,
|
||||
|
@ -86,7 +86,7 @@ setaddrs(Bits bit)
|
|||
i = bnum(bit);
|
||||
node = var[i].node;
|
||||
n = var[i].name;
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
|
||||
// disable all pieces of that variable
|
||||
for(i=0; i<nvar; i++) {
|
||||
|
@ -393,7 +393,7 @@ loop2:
|
|||
for(z=0; z<BITS; z++)
|
||||
bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
|
||||
~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
|
||||
if(bany(&bit) & !r->f.refset) {
|
||||
if(bany(&bit) && !r->f.refset) {
|
||||
// should never happen - all variables are preset
|
||||
if(debug['w'])
|
||||
print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
|
||||
|
@ -425,7 +425,7 @@ loop2:
|
|||
if(debug['R'] > 1)
|
||||
print("\n");
|
||||
paint1(r, i);
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
if(change <= 0) {
|
||||
if(debug['R'])
|
||||
print("%L $%d: %Q\n",
|
||||
|
@ -570,7 +570,7 @@ walkvardef(Node *n, Reg *r, int active)
|
|||
break;
|
||||
for(v=n->opt; v!=nil; v=v->nextinnode) {
|
||||
bn = v - var;
|
||||
r1->act.b[bn/32] |= 1L << (bn%32);
|
||||
biset(&r1->act, bn);
|
||||
}
|
||||
if(r1->f.prog->as == ABL)
|
||||
break;
|
||||
|
@ -606,7 +606,7 @@ addsplits(void)
|
|||
~(r->calahead.b[z] & addrs.b[z]);
|
||||
while(bany(&bit)) {
|
||||
i = bnum(bit);
|
||||
bit.b[i/32] &= ~(1L << (i%32));
|
||||
biclr(&bit, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -972,10 +972,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
|||
for(z=0; z<BITS; z++) {
|
||||
if(cal.b[z] == 0)
|
||||
continue;
|
||||
for(i=0; i<32; i++) {
|
||||
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
for(i=0; i<64; i++) {
|
||||
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
continue;
|
||||
v = var+z*32+i;
|
||||
v = var+z*64+i;
|
||||
if(v->node->opt == nil) // v represents fixed register, not Go variable
|
||||
continue;
|
||||
|
||||
|
@ -991,10 +991,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
|||
// This will set the bits at most twice, keeping the overall loop linear.
|
||||
v1 = v->node->opt;
|
||||
j = v1 - var;
|
||||
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
|
||||
if(v == v1 || !btest(&cal, j)) {
|
||||
for(; v1 != nil; v1 = v1->nextinnode) {
|
||||
j = v1 - var;
|
||||
cal.b[j/32] |= 1<<(j&31);
|
||||
biset(&cal, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1115,10 +1115,10 @@ paint1(Reg *r, int bn)
|
|||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L<<(bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL<<(bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
|
@ -1193,10 +1193,10 @@ paint2(Reg *r, int bn)
|
|||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb, vreg;
|
||||
uint64 bb, vreg;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
vreg = regbits;
|
||||
if(!(r->act.b[z] & bb))
|
||||
return vreg;
|
||||
|
@ -1240,15 +1240,15 @@ paint2(Reg *r, int bn)
|
|||
}
|
||||
|
||||
void
|
||||
paint3(Reg *r, int bn, int32 rb, int rn)
|
||||
paint3(Reg *r, int bn, uint32 rb, int rn)
|
||||
{
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
|
@ -1333,7 +1333,7 @@ addreg(Adr *a, int rn)
|
|||
* 10 R10
|
||||
* 12 R12
|
||||
*/
|
||||
int32
|
||||
uint32
|
||||
RtoB(int r)
|
||||
{
|
||||
if(r >= REGTMP-2 && r != 12) // excluded R9 and R10 for m and g, but not R12
|
||||
|
@ -1342,7 +1342,7 @@ RtoB(int r)
|
|||
}
|
||||
|
||||
int
|
||||
BtoR(int32 b)
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
|
||||
if(b == 0)
|
||||
|
@ -1357,7 +1357,7 @@ BtoR(int32 b)
|
|||
* ... ...
|
||||
* 31 F15
|
||||
*/
|
||||
int32
|
||||
uint32
|
||||
FtoB(int f)
|
||||
{
|
||||
|
||||
|
@ -1367,7 +1367,7 @@ FtoB(int f)
|
|||
}
|
||||
|
||||
int
|
||||
BtoF(int32 b)
|
||||
BtoF(uint32 b)
|
||||
{
|
||||
|
||||
b &= 0xfffc0000L;
|
||||
|
|
|
@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
|
|||
a->sym = linksym(sym);
|
||||
a->node = sym->def;
|
||||
a->offset = 0; // header
|
||||
a->etype = TINT32;
|
||||
a->etype = TSTRING;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -63,8 +63,8 @@ enum
|
|||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint32 LOAD(Reg*);
|
||||
uint32 STORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
|
@ -141,7 +141,7 @@ void synch(Reg*, Bits);
|
|||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
|
@ -153,10 +153,10 @@ void peep(Prog*);
|
|||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "opt.h"
|
||||
|
||||
#define NREGVAR 32 /* 16 general + 16 floating */
|
||||
#define REGBITS ((uint32)0xffffffff)
|
||||
#define REGBITS ((uint64)0xffffffffull)
|
||||
/*c2go enum {
|
||||
NREGVAR = 32,
|
||||
REGBITS = 0xffffffff,
|
||||
|
@ -71,7 +71,7 @@ setaddrs(Bits bit)
|
|||
i = bnum(bit);
|
||||
node = var[i].node;
|
||||
n = var[i].name;
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
|
||||
// disable all pieces of that variable
|
||||
for(i=0; i<nvar; i++) {
|
||||
|
@ -364,7 +364,7 @@ loop2:
|
|||
rgp->varno = i;
|
||||
change = 0;
|
||||
paint1(r, i);
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
if(change <= 0)
|
||||
continue;
|
||||
rgp->cost = change;
|
||||
|
@ -477,7 +477,7 @@ walkvardef(Node *n, Reg *r, int active)
|
|||
break;
|
||||
for(v=n->opt; v!=nil; v=v->nextinnode) {
|
||||
bn = v - var;
|
||||
r1->act.b[bn/32] |= 1L << (bn%32);
|
||||
biset(&r1->act, bn);
|
||||
}
|
||||
if(r1->f.prog->as == ACALL)
|
||||
break;
|
||||
|
@ -621,6 +621,9 @@ mkvar(Reg *r, Adr *a)
|
|||
if(r != R)
|
||||
r->use1.b[0] |= doregbits(a->index);
|
||||
|
||||
if(t >= D_INDIR && t < 2*D_INDIR)
|
||||
goto none;
|
||||
|
||||
switch(t) {
|
||||
default:
|
||||
regu = doregbits(t);
|
||||
|
@ -822,10 +825,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
|||
for(z=0; z<BITS; z++) {
|
||||
if(cal.b[z] == 0)
|
||||
continue;
|
||||
for(i=0; i<32; i++) {
|
||||
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
for(i=0; i<64; i++) {
|
||||
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
continue;
|
||||
v = var+z*32+i;
|
||||
v = var+z*64+i;
|
||||
if(v->node->opt == nil) // v represents fixed register, not Go variable
|
||||
continue;
|
||||
|
||||
|
@ -841,10 +844,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
|||
// This will set the bits at most twice, keeping the overall loop linear.
|
||||
v1 = v->node->opt;
|
||||
j = v1 - var;
|
||||
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
|
||||
if(v == v1 || !btest(&cal, j)) {
|
||||
for(; v1 != nil; v1 = v1->nextinnode) {
|
||||
j = v1 - var;
|
||||
cal.b[j/32] |= 1UL<<(j&31);
|
||||
biset(&cal, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -959,10 +962,10 @@ paint1(Reg *r, int bn)
|
|||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L<<(bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL<<(bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
|
@ -1016,55 +1019,15 @@ paint1(Reg *r, int bn)
|
|||
}
|
||||
}
|
||||
|
||||
uint32
|
||||
regset(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFFFF? BtoR(b): BtoF(b);
|
||||
if(v.type == 0)
|
||||
fatal("zero v.type for %#ux", b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 3)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
reguse(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFFFF? BtoR(b): BtoF(b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 1 || c == 2 || c == 4)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb, vreg, x;
|
||||
uint64 bb, vreg;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
vreg = regbits;
|
||||
if(!(r->act.b[z] & bb))
|
||||
return vreg;
|
||||
|
@ -1105,27 +1068,19 @@ paint2(Reg *r, int bn)
|
|||
break;
|
||||
}
|
||||
|
||||
bb = vreg;
|
||||
for(; r; r=(Reg*)r->f.s1) {
|
||||
x = r->regu & ~bb;
|
||||
if(x) {
|
||||
vreg |= reguse(r, x);
|
||||
bb |= regset(r, x);
|
||||
}
|
||||
}
|
||||
return vreg;
|
||||
}
|
||||
|
||||
void
|
||||
paint3(Reg *r, int bn, int32 rb, int rn)
|
||||
paint3(Reg *r, int bn, uint32 rb, int rn)
|
||||
{
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
|
@ -1198,7 +1153,7 @@ addreg(Adr *a, int rn)
|
|||
ostats.ncvtreg++;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
RtoB(int r)
|
||||
{
|
||||
|
||||
|
@ -1208,7 +1163,7 @@ RtoB(int r)
|
|||
}
|
||||
|
||||
int
|
||||
BtoR(int32 b)
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
b &= 0xffffL;
|
||||
if(nacl)
|
||||
|
@ -1224,7 +1179,7 @@ BtoR(int32 b)
|
|||
* ...
|
||||
* 31 X15
|
||||
*/
|
||||
int32
|
||||
uint32
|
||||
FtoB(int f)
|
||||
{
|
||||
if(f < D_X0 || f > D_X15)
|
||||
|
@ -1233,7 +1188,7 @@ FtoB(int f)
|
|||
}
|
||||
|
||||
int
|
||||
BtoF(int32 b)
|
||||
BtoF(uint32 b)
|
||||
{
|
||||
|
||||
b &= 0xFFFF0000L;
|
||||
|
|
|
@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
|
|||
a->sym = linksym(sym);
|
||||
a->node = sym->def;
|
||||
a->offset = 0; // header
|
||||
a->etype = TINT32;
|
||||
a->etype = TSTRING;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -63,8 +63,8 @@ enum
|
|||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint32 LOAD(Reg*);
|
||||
uint32 STORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
|
@ -159,7 +159,7 @@ void synch(Reg*, Bits);
|
|||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
|
@ -171,10 +171,10 @@ void peep(Prog*);
|
|||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "opt.h"
|
||||
|
||||
#define NREGVAR 16 /* 8 integer + 8 floating */
|
||||
#define REGBITS ((uint32)0xffff)
|
||||
#define REGBITS ((uint64)0xffffull)
|
||||
/*c2go enum {
|
||||
NREGVAR = 16,
|
||||
REGBITS = (1<<NREGVAR) - 1,
|
||||
|
@ -71,7 +71,7 @@ setaddrs(Bits bit)
|
|||
i = bnum(bit);
|
||||
node = var[i].node;
|
||||
n = var[i].name;
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
|
||||
// disable all pieces of that variable
|
||||
for(i=0; i<nvar; i++) {
|
||||
|
@ -336,7 +336,7 @@ loop2:
|
|||
rgp->varno = i;
|
||||
change = 0;
|
||||
paint1(r, i);
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
if(change <= 0)
|
||||
continue;
|
||||
rgp->cost = change;
|
||||
|
@ -446,7 +446,7 @@ walkvardef(Node *n, Reg *r, int active)
|
|||
break;
|
||||
for(v=n->opt; v!=nil; v=v->nextinnode) {
|
||||
bn = v - var;
|
||||
r1->act.b[bn/32] |= 1L << (bn%32);
|
||||
biset(&r1->act, bn);
|
||||
}
|
||||
if(r1->f.prog->as == ACALL)
|
||||
break;
|
||||
|
@ -788,10 +788,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
|||
for(z=0; z<BITS; z++) {
|
||||
if(cal.b[z] == 0)
|
||||
continue;
|
||||
for(i=0; i<32; i++) {
|
||||
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
for(i=0; i<64; i++) {
|
||||
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
continue;
|
||||
v = var+z*32+i;
|
||||
v = var+z*64+i;
|
||||
if(v->node->opt == nil) // v represents fixed register, not Go variable
|
||||
continue;
|
||||
|
||||
|
@ -807,10 +807,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
|||
// This will set the bits at most twice, keeping the overall loop linear.
|
||||
v1 = v->node->opt;
|
||||
j = v1 - var;
|
||||
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
|
||||
if(v == v1 || !btest(&cal, j)) {
|
||||
for(; v1 != nil; v1 = v1->nextinnode) {
|
||||
j = v1 - var;
|
||||
cal.b[j/32] |= 1<<(j&31);
|
||||
biset(&cal, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -926,10 +926,10 @@ paint1(Reg *r, int bn)
|
|||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L<<(bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL<<(bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
|
@ -995,53 +995,15 @@ paint1(Reg *r, int bn)
|
|||
}
|
||||
}
|
||||
|
||||
uint32
|
||||
regset(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFF ? BtoR(b): BtoF(b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 3)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
reguse(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFF ? BtoR(b): BtoF(b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 1 || c == 2 || c == 4)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb, vreg, x;
|
||||
uint64 bb, vreg;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
vreg = regbits;
|
||||
if(!(r->act.b[z] & bb))
|
||||
return vreg;
|
||||
|
@ -1082,27 +1044,19 @@ paint2(Reg *r, int bn)
|
|||
break;
|
||||
}
|
||||
|
||||
bb = vreg;
|
||||
for(; r; r=(Reg*)r->f.s1) {
|
||||
x = r->regu & ~bb;
|
||||
if(x) {
|
||||
vreg |= reguse(r, x);
|
||||
bb |= regset(r, x);
|
||||
}
|
||||
}
|
||||
return vreg;
|
||||
}
|
||||
|
||||
void
|
||||
paint3(Reg *r, int bn, int32 rb, int rn)
|
||||
paint3(Reg *r, int bn, uint32 rb, int rn)
|
||||
{
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
|
@ -1175,7 +1129,7 @@ addreg(Adr *a, int rn)
|
|||
ostats.ncvtreg++;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
RtoB(int r)
|
||||
{
|
||||
|
||||
|
@ -1185,7 +1139,7 @@ RtoB(int r)
|
|||
}
|
||||
|
||||
int
|
||||
BtoR(int32 b)
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
|
||||
b &= 0xffL;
|
||||
|
@ -1194,7 +1148,7 @@ BtoR(int32 b)
|
|||
return bitno(b) + D_AX;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
FtoB(int f)
|
||||
{
|
||||
if(f < D_X0 || f > D_X7)
|
||||
|
@ -1203,7 +1157,7 @@ FtoB(int f)
|
|||
}
|
||||
|
||||
int
|
||||
BtoF(int32 b)
|
||||
BtoF(uint32 b)
|
||||
{
|
||||
b &= 0xFF00L;
|
||||
if(b == 0)
|
||||
|
|
|
@ -900,7 +900,7 @@ ret:
|
|||
void
|
||||
clearfat(Node *nl)
|
||||
{
|
||||
uint64 w, c, q, t;
|
||||
uint64 w, c, q, t, boff;
|
||||
Node dst, end, r0, *f;
|
||||
Prog *p, *pl;
|
||||
|
||||
|
@ -944,6 +944,8 @@ clearfat(Node *nl)
|
|||
patch(gbranch(ABNE, T, 0), pl);
|
||||
|
||||
regfree(&end);
|
||||
// The loop leaves R3 on the last zeroed dword
|
||||
boff = 8;
|
||||
} else if(q >= 4) {
|
||||
p = gins(ASUB, N, &dst);
|
||||
p->from.type = D_CONST;
|
||||
|
@ -953,17 +955,21 @@ clearfat(Node *nl)
|
|||
afunclit(&p->to, f);
|
||||
// 4 and 128 = magic constants: see ../../runtime/asm_power64x.s
|
||||
p->to.offset = 4*(128-q);
|
||||
} else
|
||||
for(t = 0; t < q; t++) {
|
||||
p = gins(AMOVD, &r0, &dst);
|
||||
p->to.type = D_OREG;
|
||||
p->to.offset = 8*t;
|
||||
// duffzero leaves R3 on the last zeroed dword
|
||||
boff = 8;
|
||||
} else {
|
||||
for(t = 0; t < q; t++) {
|
||||
p = gins(AMOVD, &r0, &dst);
|
||||
p->to.type = D_OREG;
|
||||
p->to.offset = 8*t;
|
||||
}
|
||||
boff = 8*q;
|
||||
}
|
||||
|
||||
for(t = 0; t < c; t++) {
|
||||
p = gins(AMOVB, &r0, &dst);
|
||||
p->to.type = D_OREG;
|
||||
p->to.offset = t;
|
||||
p->to.offset = t+boff;
|
||||
}
|
||||
reg[REGRT1]--;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ datagostring(Strlit *sval, Addr *a)
|
|||
a->reg = NREG;
|
||||
a->node = sym->def;
|
||||
a->offset = 0; // header
|
||||
a->etype = TINT32;
|
||||
a->etype = TSTRING;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1001,10 +1001,13 @@ hard:
|
|||
Prog*
|
||||
gins(int as, Node *f, Node *t)
|
||||
{
|
||||
//int32 w;
|
||||
int32 w;
|
||||
Prog *p;
|
||||
Addr af, at;
|
||||
|
||||
// TODO(austin): Add self-move test like in 6g (but be careful
|
||||
// of truncation moves)
|
||||
|
||||
memset(&af, 0, sizeof af);
|
||||
memset(&at, 0, sizeof at);
|
||||
if(f != N)
|
||||
|
@ -1021,9 +1024,6 @@ gins(int as, Node *f, Node *t)
|
|||
if(debug['g'])
|
||||
print("%P\n", p);
|
||||
|
||||
// TODO(minux): enable these.
|
||||
// right now it fails on MOVD $type."".TypeAssertionError(SB) [width=1], R7 [width=8]
|
||||
/*
|
||||
w = 0;
|
||||
switch(as) {
|
||||
case AMOVB:
|
||||
|
@ -1046,15 +1046,16 @@ gins(int as, Node *f, Node *t)
|
|||
break;
|
||||
case AMOVD:
|
||||
case AMOVDU:
|
||||
if(af.type == D_CONST)
|
||||
break;
|
||||
w = 8;
|
||||
break;
|
||||
}
|
||||
if(w != 0 && ((f != N && af.width < w) || (t != N && at.width > w))) {
|
||||
if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != D_REG && at.width > w))) {
|
||||
dump("f", f);
|
||||
dump("t", t);
|
||||
fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
|
||||
}
|
||||
*/
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -1116,12 +1117,9 @@ naddr(Node *n, Addr *a, int canemitcode)
|
|||
|
||||
case ONAME:
|
||||
a->etype = 0;
|
||||
a->width = 0;
|
||||
a->reg = NREG;
|
||||
if(n->type != T) {
|
||||
if(n->type != T)
|
||||
a->etype = simtype[n->type->etype];
|
||||
a->width = n->type->width;
|
||||
}
|
||||
a->offset = n->xoffset;
|
||||
s = n->sym;
|
||||
a->node = n->orig;
|
||||
|
@ -1242,15 +1240,16 @@ naddr(Node *n, Addr *a, int canemitcode)
|
|||
naddr(n->left, a, canemitcode);
|
||||
a->etype = simtype[tptr];
|
||||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // len(nil)
|
||||
break; // itab(nil)
|
||||
a->width = widthptr;
|
||||
break;
|
||||
|
||||
case OSPTR:
|
||||
// pointer in a string or slice
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->etype = simtype[tptr];
|
||||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // ptr(nil)
|
||||
a->etype = simtype[tptr];
|
||||
a->offset += Array_array;
|
||||
a->width = widthptr;
|
||||
break;
|
||||
|
@ -1262,6 +1261,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
|||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // len(nil)
|
||||
a->offset += Array_nel;
|
||||
a->width = widthint;
|
||||
break;
|
||||
|
||||
case OCAP:
|
||||
|
@ -1271,6 +1271,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
|||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // cap(nil)
|
||||
a->offset += Array_cap;
|
||||
a->width = widthint;
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
|
@ -1288,6 +1289,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
|||
default:
|
||||
fatal("naddr: OADDR %d\n", a->type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,24 +70,40 @@ struct Reg
|
|||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu; // register used bitmap
|
||||
uint64 regu; // register used bitmap
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
/*c2go extern Reg *R; */
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
|
@ -104,7 +120,7 @@ EXTERN Rgn* rgp;
|
|||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits;
|
||||
EXTERN int32 exregbits; // TODO(austin) not used; remove
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
|
@ -118,10 +134,8 @@ EXTERN struct
|
|||
{
|
||||
int32 ncvtreg;
|
||||
int32 nspill;
|
||||
int32 nreload;
|
||||
int32 ndelmov;
|
||||
int32 nvar;
|
||||
int32 naddr;
|
||||
} ostats;
|
||||
|
||||
/*
|
||||
|
@ -133,10 +147,10 @@ void addmove(Reg*, int, int, int);
|
|||
Bits mkvar(Reg*, Adr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
uint64 allreg(uint64, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
uint64 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint64, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
|
@ -160,8 +174,8 @@ typedef struct ProgInfo ProgInfo;
|
|||
struct ProgInfo
|
||||
{
|
||||
uint32 flags; // the bits below
|
||||
uint64 reguse; // required registers used by this instruction
|
||||
uint64 regset; // required registers set by this instruction
|
||||
uint64 reguse; // registers implicitly used by this instruction
|
||||
uint64 regset; // registers implicitly set by this instruction
|
||||
uint64 regindex; // registers used by addressing mode
|
||||
};
|
||||
|
||||
|
@ -182,20 +196,21 @@ enum
|
|||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Register in middle; never written.
|
||||
|
||||
// Register in middle (Prog.reg); only ever read.
|
||||
RegRead = 1<<12,
|
||||
CanRegRead = 1<<13,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<14,
|
||||
RightRead = 1<<15,
|
||||
RightWrite = 1<<16,
|
||||
|
||||
// Instruction updates whichever of from/to is type D_OREG
|
||||
PostInc = 1<<17,
|
||||
|
||||
// Instruction kinds
|
||||
|
|
|
@ -44,13 +44,15 @@ peep(Prog *p)
|
|||
void
|
||||
excise(Flow *r)
|
||||
{
|
||||
Prog *p;
|
||||
Prog *p, *l;
|
||||
|
||||
p = r->prog;
|
||||
if(debug['P'] && debug['v'])
|
||||
print("%P ===delete===\n", p);
|
||||
l = p->link;
|
||||
*p = zprog;
|
||||
p->as = ANOP;
|
||||
p->link = l;
|
||||
ostats.ndelmov++;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,11 +96,8 @@ static ProgInfo progtable[ALAST] = {
|
|||
[ABGT]= {Cjmp},
|
||||
[ABLE]= {Cjmp},
|
||||
[ARETURN]= {Break},
|
||||
// In addtion, duffzero reads R0,R2 and writes R2. This fact must be
|
||||
// encoded in peep.c (TODO)
|
||||
|
||||
[ADUFFZERO]= {Call},
|
||||
// In addtion, duffcopy reads R0,R2,R3 and writes R2,R3. This fact must be
|
||||
// encoded in peep.c (TODO)
|
||||
[ADUFFCOPY]= {Call},
|
||||
};
|
||||
|
||||
|
@ -118,14 +115,14 @@ proginfo(ProgInfo *info, Prog *p)
|
|||
info->flags |= /*CanRegRead |*/ RightRead;
|
||||
}
|
||||
|
||||
if(p->from.type == D_OREG && p->from.reg != NREG) {
|
||||
info->reguse |= RtoB(p->from.reg);
|
||||
if((p->from.type == D_OREG || p->from.type == D_CONST) && p->from.reg != NREG) {
|
||||
info->regindex |= RtoB(p->from.reg);
|
||||
if(info->flags & PostInc) {
|
||||
info->regset |= RtoB(p->from.reg);
|
||||
}
|
||||
}
|
||||
if(p->to.type == D_OREG && p->to.reg != NREG) {
|
||||
info->reguse |= RtoB(p->to.reg);
|
||||
if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) {
|
||||
info->regindex |= RtoB(p->to.reg);
|
||||
if(info->flags & PostInc) {
|
||||
info->regset |= RtoB(p->to.reg);
|
||||
}
|
||||
|
@ -135,4 +132,13 @@ proginfo(ProgInfo *info, Prog *p)
|
|||
info->flags &= ~LeftRead;
|
||||
info->flags |= LeftAddr;
|
||||
}
|
||||
|
||||
if(p->as == ADUFFZERO) {
|
||||
info->reguse |= RtoB(0) | RtoB(2);
|
||||
info->regset |= RtoB(2);
|
||||
}
|
||||
if(p->as == ADUFFCOPY) {
|
||||
info->reguse |= RtoB(0) | RtoB(2) | RtoB(3);
|
||||
info->regset |= RtoB(2) | RtoB(3);
|
||||
}
|
||||
}
|
||||
|
|
1214
src/cmd/9g/reg.c
1214
src/cmd/9g/reg.c
File diff suppressed because it is too large
Load diff
|
@ -131,7 +131,7 @@ enum
|
|||
C_NCLASS, /* must be the last */
|
||||
};
|
||||
|
||||
enum as
|
||||
enum
|
||||
{
|
||||
AXXX,
|
||||
AADD,
|
||||
|
@ -501,7 +501,7 @@ enum
|
|||
D_R0 = 0, // type is D_REG
|
||||
D_F0 = D_R0+NREG, // type is D_FREG
|
||||
|
||||
/* reg names iff type is D_SPR */
|
||||
/* reg names in offset field iff type is D_SPR */
|
||||
D_XER = 1,
|
||||
D_LR = 8,
|
||||
D_CTR = 9
|
||||
|
|
|
@ -95,11 +95,11 @@ int
|
|||
bnum(Bits a)
|
||||
{
|
||||
int i;
|
||||
int32 b;
|
||||
uint64 b;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(b = a.b[i])
|
||||
return 32*i + bitno(b);
|
||||
return 64*i + bitno(b);
|
||||
fatal("bad in bnum");
|
||||
return 0;
|
||||
}
|
||||
|
@ -110,27 +110,35 @@ blsh(uint n)
|
|||
Bits c;
|
||||
|
||||
c = zbits;
|
||||
c.b[n/32] = 1L << (n%32);
|
||||
c.b[n/64] = 1LL << (n%64);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
int
|
||||
bset(Bits a, uint n)
|
||||
btest(Bits *a, uint n)
|
||||
{
|
||||
if(a.b[n/32] & (1L << (n%32)))
|
||||
return 1;
|
||||
return 0;
|
||||
return (a->b[n/64] & (1LL << (n%64))) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
biset(Bits *a, uint n)
|
||||
{
|
||||
a->b[n/64] |= 1LL << (n%64);
|
||||
}
|
||||
|
||||
void
|
||||
biclr(Bits *a, uint n)
|
||||
{
|
||||
a->b[n/64] &= ~(1LL << (n%64));
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
bitno(int32 b)
|
||||
bitno(uint64 b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<32; i++)
|
||||
if(b & (1L<<i))
|
||||
for(i=0; i<64; i++)
|
||||
if(b & (1LL<<i))
|
||||
return i;
|
||||
fatal("bad in bitno");
|
||||
return 0;
|
||||
|
@ -157,7 +165,7 @@ Qconv(Fmt *fp)
|
|||
if(var[i].offset != 0)
|
||||
fmtprint(fp, "%+lld", (vlong)var[i].offset);
|
||||
}
|
||||
bits.b[i/32] &= ~(1L << (i%32));
|
||||
biclr(&bits, i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -704,13 +704,13 @@ enum
|
|||
Ecomplit = 1<<11, // type in composite literal
|
||||
};
|
||||
|
||||
#define BITS 5
|
||||
#define NVAR (BITS*sizeof(uint32)*8)
|
||||
#define BITS 3
|
||||
#define NVAR (BITS*sizeof(uint64)*8)
|
||||
|
||||
typedef struct Bits Bits;
|
||||
struct Bits
|
||||
{
|
||||
uint32 b[BITS];
|
||||
uint64 b[BITS];
|
||||
};
|
||||
|
||||
EXTERN Bits zbits;
|
||||
|
@ -1027,12 +1027,14 @@ int Qconv(Fmt *fp);
|
|||
Bits band(Bits a, Bits b);
|
||||
int bany(Bits *a);
|
||||
int beq(Bits a, Bits b);
|
||||
int bitno(int32 b);
|
||||
int bitno(uint64 b);
|
||||
Bits blsh(uint n);
|
||||
Bits bnot(Bits a);
|
||||
int bnum(Bits a);
|
||||
Bits bor(Bits a, Bits b);
|
||||
int bset(Bits a, uint n);
|
||||
int btest(Bits *a, uint n);
|
||||
void biset(Bits *a, uint n);
|
||||
void biclr(Bits *a, uint n);
|
||||
|
||||
/*
|
||||
* bv.c
|
||||
|
|
|
@ -101,6 +101,10 @@ func testDisasm(t *testing.T, flags ...string) {
|
|||
}
|
||||
|
||||
func TestDisasm(t *testing.T) {
|
||||
switch runtime.GOARCH {
|
||||
case "power64", "power64le":
|
||||
t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
|
||||
}
|
||||
testDisasm(t)
|
||||
}
|
||||
|
||||
|
@ -109,5 +113,9 @@ func TestDisasmExtld(t *testing.T) {
|
|||
case "plan9", "windows":
|
||||
t.Skipf("skipping on %s", runtime.GOOS)
|
||||
}
|
||||
switch runtime.GOARCH {
|
||||
case "power64", "power64le":
|
||||
t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH)
|
||||
}
|
||||
testDisasm(t, "-ldflags=-linkmode=external")
|
||||
}
|
||||
|
|
|
@ -259,11 +259,12 @@ Dconv(Fmt *fp)
|
|||
sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v);
|
||||
else
|
||||
sprint(str, "%.5lux(BRANCH)", v);
|
||||
} else
|
||||
if(a->sym != nil)
|
||||
sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
|
||||
else
|
||||
sprint(str, "%lld(APC)", a->offset);
|
||||
} else if(a->u.branch != nil)
|
||||
sprint(str, "%lld", a->u.branch->pc);
|
||||
else if(a->sym != nil)
|
||||
sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
|
||||
else
|
||||
sprint(str, "%lld(APC)", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
// +build power64 power64le
|
||||
|
||||
#include "textflag.h"
|
||||
#include "funcdata.h"
|
||||
|
||||
// makeFuncStub is the code half of the function returned by MakeFunc.
|
||||
// See the comment on the declaration of makeFuncStub in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
// No arg size here, runtime pulls arg map out of the func value.
|
||||
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R11, 8(R1)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, 16(R1)
|
||||
|
@ -20,8 +22,9 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
|
|||
// methodValueCall is the code half of the function returned by makeMethodValue.
|
||||
// See the comment on the declaration of methodValueCall in makefunc.go
|
||||
// for more details.
|
||||
// No argsize here, gc generates argsize info at call site.
|
||||
// No arg size here; runtime pulls arg map out of the func value.
|
||||
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
|
||||
NO_LOCAL_POINTERS
|
||||
MOVD R11, 8(R1)
|
||||
MOVD $argframe+0(FP), R3
|
||||
MOVD R3, 16(R1)
|
||||
|
|
|
@ -86,7 +86,7 @@ TEXT runtime·reginit(SB),NOSPLIT,$-8-0
|
|||
// void gosave(Gobuf*)
|
||||
// save state in Gobuf; setjmp
|
||||
TEXT runtime·gosave(SB), NOSPLIT, $-8-8
|
||||
MOVD gobuf+0(FP), R3
|
||||
MOVD buf+0(FP), R3
|
||||
MOVD R1, gobuf_sp(R3)
|
||||
MOVD LR, R31
|
||||
MOVD R31, gobuf_pc(R3)
|
||||
|
@ -99,7 +99,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $-8-8
|
|||
// void gogo(Gobuf*)
|
||||
// restore state from Gobuf; longjmp
|
||||
TEXT runtime·gogo(SB), NOSPLIT, $-8-8
|
||||
MOVD gobuf+0(FP), R5
|
||||
MOVD buf+0(FP), R5
|
||||
MOVD gobuf_g(R5), g // make sure g is not nil
|
||||
MOVD 0(g), R4
|
||||
MOVD gobuf_sp(R5), R1
|
||||
|
@ -299,7 +299,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
|
|||
// Note: can't just "BR NAME(SB)" - bad inlining results.
|
||||
|
||||
TEXT ·reflectcall(SB), NOSPLIT, $-8-24
|
||||
MOVW argsize+16(FP), R3
|
||||
MOVWZ n+16(FP), R3
|
||||
DISPATCH(runtime·call16, 16)
|
||||
DISPATCH(runtime·call32, 32)
|
||||
DISPATCH(runtime·call64, 64)
|
||||
|
@ -335,8 +335,8 @@ TEXT ·reflectcall(SB), NOSPLIT, $-8-24
|
|||
TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
|
||||
NO_LOCAL_POINTERS; \
|
||||
/* copy arguments to stack */ \
|
||||
MOVD argptr+8(FP), R3; \
|
||||
MOVW argsize+16(FP), R4; \
|
||||
MOVD arg+8(FP), R3; \
|
||||
MOVWZ n+16(FP), R4; \
|
||||
MOVD R1, R5; \
|
||||
ADD $(8-1), R5; \
|
||||
SUB $1, R3; \
|
||||
|
@ -353,9 +353,9 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
|
|||
PCDATA $PCDATA_StackMapIndex, $0; \
|
||||
BL (CTR); \
|
||||
/* copy return values back */ \
|
||||
MOVD argptr+8(FP), R3; \
|
||||
MOVW argsize+16(FP), R4; \
|
||||
MOVW retoffset+20(FP), R6; \
|
||||
MOVD arg+8(FP), R3; \
|
||||
MOVWZ n+16(FP), R4; \
|
||||
MOVWZ retoffset+20(FP), R6; \
|
||||
MOVD R1, R5; \
|
||||
ADD R6, R5; \
|
||||
ADD R6, R3; \
|
||||
|
@ -398,7 +398,7 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
// bool cas(int32 *val, int32 old, int32 new)
|
||||
// bool cas(uint32 *ptr, uint32 old, uint32 new)
|
||||
// Atomically:
|
||||
// if(*val == old){
|
||||
// *val = new;
|
||||
|
@ -406,9 +406,9 @@ CALLFN(·call1073741824, 1073741824)
|
|||
// } else
|
||||
// return 0;
|
||||
TEXT runtime·cas(SB), NOSPLIT, $0-17
|
||||
MOVD p+0(FP), R3
|
||||
MOVW old+8(FP), R4
|
||||
MOVW new+12(FP), R5
|
||||
MOVD ptr+0(FP), R3
|
||||
MOVWZ old+8(FP), R4
|
||||
MOVWZ new+12(FP), R5
|
||||
cas_again:
|
||||
SYNC
|
||||
LWAR (R3), R6
|
||||
|
@ -425,7 +425,7 @@ cas_fail:
|
|||
MOVD $0, R3
|
||||
BR -5(PC)
|
||||
|
||||
// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
|
||||
// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
|
||||
// Atomically:
|
||||
// if(*val == *old){
|
||||
// *val = new;
|
||||
|
@ -434,7 +434,7 @@ cas_fail:
|
|||
// return 0;
|
||||
// }
|
||||
TEXT runtime·cas64(SB), NOSPLIT, $0-25
|
||||
MOVD p+0(FP), R3
|
||||
MOVD ptr+0(FP), R3
|
||||
MOVD old+8(FP), R4
|
||||
MOVD new+16(FP), R5
|
||||
cas64_again:
|
||||
|
@ -475,12 +475,12 @@ TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
|
|||
TEXT runtime·casp1(SB), NOSPLIT, $0-25
|
||||
BR runtime·cas64(SB)
|
||||
|
||||
// uint32 xadd(uint32 volatile *val, int32 delta)
|
||||
// uint32 xadd(uint32 volatile *ptr, int32 delta)
|
||||
// Atomically:
|
||||
// *val += delta;
|
||||
// return *val;
|
||||
TEXT runtime·xadd(SB), NOSPLIT, $0-20
|
||||
MOVD p+0(FP), R4
|
||||
MOVD ptr+0(FP), R4
|
||||
MOVW delta+8(FP), R5
|
||||
SYNC
|
||||
LWAR (R4), R3
|
||||
|
@ -493,7 +493,7 @@ TEXT runtime·xadd(SB), NOSPLIT, $0-20
|
|||
RETURN
|
||||
|
||||
TEXT runtime·xadd64(SB), NOSPLIT, $0-24
|
||||
MOVD p+0(FP), R4
|
||||
MOVD ptr+0(FP), R4
|
||||
MOVD delta+8(FP), R5
|
||||
SYNC
|
||||
LDAR (R4), R3
|
||||
|
@ -506,7 +506,7 @@ TEXT runtime·xadd64(SB), NOSPLIT, $0-24
|
|||
RETURN
|
||||
|
||||
TEXT runtime·xchg(SB), NOSPLIT, $0-20
|
||||
MOVD p+0(FP), R4
|
||||
MOVD ptr+0(FP), R4
|
||||
MOVW new+8(FP), R5
|
||||
SYNC
|
||||
LWAR (R4), R3
|
||||
|
@ -518,7 +518,7 @@ TEXT runtime·xchg(SB), NOSPLIT, $0-20
|
|||
RETURN
|
||||
|
||||
TEXT runtime·xchg64(SB), NOSPLIT, $0-24
|
||||
MOVD p+0(FP), R4
|
||||
MOVD ptr+0(FP), R4
|
||||
MOVD new+8(FP), R5
|
||||
SYNC
|
||||
LDAR (R4), R3
|
||||
|
@ -651,7 +651,7 @@ TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16
|
|||
RETURN
|
||||
|
||||
TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
|
||||
MOVD sp+0(FP), R3
|
||||
MOVD argp+0(FP), R3
|
||||
SUB $8, R3
|
||||
MOVD R3, ret+8(FP)
|
||||
RETURN
|
||||
|
@ -695,16 +695,17 @@ TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
|
|||
TEXT runtime·memeq(SB),NOSPLIT,$-8-25
|
||||
MOVD a+0(FP), R3
|
||||
MOVD b+8(FP), R4
|
||||
MOVD count+16(FP), R5
|
||||
MOVD size+16(FP), R5
|
||||
SUB $1, R3
|
||||
SUB $1, R4
|
||||
ADD R3, R5, R8
|
||||
loop:
|
||||
CMP R3, R8
|
||||
BNE 4(PC)
|
||||
BNE test
|
||||
MOVD $1, R3
|
||||
MOVB R3, ret+24(FP)
|
||||
RETURN
|
||||
test:
|
||||
MOVBZU 1(R3), R6
|
||||
MOVBZU 1(R4), R7
|
||||
CMP R6, R7
|
||||
|
@ -828,7 +829,7 @@ notfound:
|
|||
// in ../../cmd/9g/ggen.c:/^clearfat.
|
||||
// R0: always zero
|
||||
// R3 (aka REGRT1): ptr to memory to be zeroed - 8
|
||||
// R3 is updated as a side effect.
|
||||
// On return, R3 points to the last zeroed dword.
|
||||
TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
|
||||
MOVDU R0, 8(R3)
|
||||
MOVDU R0, 8(R3)
|
||||
|
@ -964,7 +965,7 @@ TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
|
|||
MOVD g_m(g), R4
|
||||
MOVWZ m_fastrand(R4), R3
|
||||
ADD R3, R3
|
||||
CMP R3, $0
|
||||
CMPW R3, $0
|
||||
BGE 2(PC)
|
||||
XOR $0x88888eef, R3
|
||||
MOVW R3, m_fastrand(R4)
|
||||
|
@ -979,3 +980,9 @@ TEXT runtime·return0(SB), NOSPLIT, $0
|
|||
// Must obey the gcc calling convention.
|
||||
TEXT _cgo_topofstack(SB),NOSPLIT,$0
|
||||
MOVD R0, 26(R0)
|
||||
|
||||
// The top-most function running on a goroutine
|
||||
// returns to goexit+PCQuantum.
|
||||
TEXT runtime·goexit(SB),NOSPLIT,$-8-0
|
||||
MOVD R0, R0 // NOP
|
||||
BL runtime·goexit1(SB) // does not return
|
||||
|
|
|
@ -137,7 +137,7 @@ func infoBigStruct() []byte {
|
|||
BitsScalar, BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64
|
||||
BitsPointer, BitsDead, // i string
|
||||
}
|
||||
case "amd64":
|
||||
case "amd64", "power64", "power64le":
|
||||
return []byte{
|
||||
BitsPointer, // q *int
|
||||
BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte
|
||||
|
@ -153,12 +153,6 @@ func infoBigStruct() []byte {
|
|||
BitsScalar, BitsScalar, BitsDead, BitsScalar, BitsScalar, // t int; y uint16; u uint64
|
||||
BitsPointer, BitsDead, // i string
|
||||
}
|
||||
case "power64", "power64le":
|
||||
return []byte{
|
||||
BitsPointer, BitsScalar, BitsScalar, BitsScalar,
|
||||
BitsMultiWord, BitsSlice, BitsScalar, BitsScalar,
|
||||
BitsScalar, BitsScalar, BitsMultiWord, BitsString,
|
||||
}
|
||||
default:
|
||||
panic("unknown arch")
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@
|
|||
|
||||
enum {
|
||||
Debug = 0,
|
||||
DebugPtrs = 0, // if 1, print trace of every pointer load during GC
|
||||
ConcurrentSweep = 1,
|
||||
|
||||
FinBlockSize = 4*1024,
|
||||
|
|
|
@ -69,7 +69,7 @@ runtime·recovery_m(G *gp)
|
|||
// each call to deferproc.
|
||||
// (The pc we're returning to does pop pop
|
||||
// before it tests the return value.)
|
||||
// On the arm there are 2 saved LRs mixed in too.
|
||||
// On the arm and power there are 2 saved LRs mixed in too.
|
||||
if(thechar == '5' || thechar == '9')
|
||||
gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr);
|
||||
else
|
||||
|
|
|
@ -226,6 +226,12 @@ runtime·check(void)
|
|||
if(z != 4)
|
||||
runtime·throw("cas4");
|
||||
|
||||
z = 0xffffffff;
|
||||
if(!runtime·cas(&z, 0xffffffff, 0xfffffffe))
|
||||
runtime·throw("cas5");
|
||||
if(z != 0xfffffffe)
|
||||
runtime·throw("cas6");
|
||||
|
||||
k = (byte*)0xfedcb123;
|
||||
if(sizeof(void*) == 8)
|
||||
k = (byte*)((uintptr)k<<10);
|
||||
|
|
|
@ -124,7 +124,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
|
|||
|
||||
if(runtime·gotraceback(&crash)){
|
||||
runtime·goroutineheader(gp);
|
||||
runtime·traceback(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LINK(info, ctxt), gp);
|
||||
runtime·tracebacktrap(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LINK(info, ctxt), gp);
|
||||
runtime·tracebackothers(gp);
|
||||
runtime·printf("\n");
|
||||
runtime·dumpregs(info, ctxt);
|
||||
|
|
68
test/clearfat.go
Normal file
68
test/clearfat.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
// runoutput
|
||||
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Check that {5,6,8,9}g/ggen.c:clearfat is zeroing the entire object.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const ntest = 1100
|
||||
|
||||
func main() {
|
||||
var decls, calls bytes.Buffer
|
||||
|
||||
for i := 1; i <= ntest; i++ {
|
||||
s := strconv.Itoa(i)
|
||||
decls.WriteString(strings.Replace(decl, "$", s, -1))
|
||||
calls.WriteString(strings.Replace("poison$()\n\tclearfat$()\n\t", "$", s, -1))
|
||||
}
|
||||
|
||||
program = strings.Replace(program, "$DECLS", decls.String(), 1)
|
||||
program = strings.Replace(program, "$CALLS", calls.String(), 1)
|
||||
fmt.Print(program)
|
||||
}
|
||||
|
||||
var program = `package main
|
||||
|
||||
var count int
|
||||
|
||||
$DECLS
|
||||
|
||||
func main() {
|
||||
$CALLS
|
||||
if count != 0 {
|
||||
println("failed", count, "case(s)")
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const decl = `
|
||||
func poison$() {
|
||||
// Grow and poison the stack space that will be used by clearfat$
|
||||
var t [2*$]byte
|
||||
for i := range t {
|
||||
t[i] = 0xff
|
||||
}
|
||||
}
|
||||
|
||||
func clearfat$() {
|
||||
var t [$]byte
|
||||
|
||||
for _, x := range t {
|
||||
if x != 0 {
|
||||
// println("clearfat$: index", i, "expected 0, got", x)
|
||||
count++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
|
@ -634,8 +634,8 @@ func newT40() *T40 {
|
|||
|
||||
func bad40() {
|
||||
t := newT40()
|
||||
printnl()
|
||||
_ = t
|
||||
printnl()
|
||||
}
|
||||
|
||||
func good40() {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// errorcheck -0 -d=nil
|
||||
// Fails on power64x because of incomplete optimization. See issue 9058.
|
||||
// +build !power64,!power64le
|
||||
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
|
|
Loading…
Reference in a new issue