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