mirror of https://github.com/golang/go.git
grab bag of changes aimed at getting stack splitting to work:
- morestack support for 5l and arm runtime - argsize support in 5c, 5l, ar and nm. assembly code from 5a will break in interesting ways unless NOSPLIT is specified - explicit cond execution constants - fix 5l output to use %d instead of %ld so that negative values show. - added a lot of code to arm/asm.s. runtime entry code almost working currently aborts at gogo not implemented R=rsc APPROVED=rsc DELTA=305 (125 added, 29 deleted, 151 changed) OCL=30246 CL=30347
This commit is contained in:
parent
d45442ed65
commit
1ac2cfc720
|
|
@ -61,6 +61,7 @@ typedef struct Rgn Rgn;
|
||||||
struct Adr
|
struct Adr
|
||||||
{
|
{
|
||||||
int32 offset;
|
int32 offset;
|
||||||
|
int32 offset2;
|
||||||
double dval;
|
double dval;
|
||||||
char sval[NSNAME];
|
char sval[NSNAME];
|
||||||
Ieee ieee;
|
Ieee ieee;
|
||||||
|
|
@ -140,7 +141,7 @@ struct Reg
|
||||||
int32 regu;
|
int32 regu;
|
||||||
int32 loop; /* could be shorter */
|
int32 loop; /* could be shorter */
|
||||||
|
|
||||||
|
|
||||||
Reg* log5;
|
Reg* log5;
|
||||||
int32 active;
|
int32 active;
|
||||||
|
|
||||||
|
|
@ -362,10 +363,10 @@ int32 FtoB(int);
|
||||||
int BtoR(int32);
|
int BtoR(int32);
|
||||||
int BtoF(int32);
|
int BtoF(int32);
|
||||||
|
|
||||||
void predicate(void);
|
void predicate(void);
|
||||||
int isbranch(Prog *);
|
int isbranch(Prog *);
|
||||||
int predicable(Prog *p);
|
int predicable(Prog *p);
|
||||||
int modifiescpsr(Prog *p);
|
int modifiescpsr(Prog *p);
|
||||||
|
|
||||||
#pragma varargck type "A" int
|
#pragma varargck type "A" int
|
||||||
#pragma varargck type "B" Bits
|
#pragma varargck type "B" Bits
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
#define EXTERN
|
#define EXTERN
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
|
|
||||||
|
|
@ -71,9 +72,9 @@ Bconv(Fmt *fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *extra [] = {
|
char *extra [] = {
|
||||||
".EQ", ".NE", ".CS", ".CC",
|
".EQ", ".NE", ".CS", ".CC",
|
||||||
".MI", ".PL", ".VS", ".VC",
|
".MI", ".PL", ".VS", ".VC",
|
||||||
".HI", ".LS", ".GE", ".LT",
|
".HI", ".LS", ".GE", ".LT",
|
||||||
".GT", ".LE", "", ".NV",
|
".GT", ".LE", "", ".NV",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -86,7 +87,7 @@ Pconv(Fmt *fp)
|
||||||
|
|
||||||
p = va_arg(fp->args, Prog*);
|
p = va_arg(fp->args, Prog*);
|
||||||
a = p->as;
|
a = p->as;
|
||||||
s = p->scond;
|
s = p->scond;
|
||||||
strcpy(sc, extra[s & C_SCOND]);
|
strcpy(sc, extra[s & C_SCOND]);
|
||||||
if(s & C_SBIT)
|
if(s & C_SBIT)
|
||||||
strcat(sc, ".S");
|
strcat(sc, ".S");
|
||||||
|
|
@ -162,6 +163,10 @@ Dconv(Fmt *fp)
|
||||||
sprint(str, "$%N", a);
|
sprint(str, "$%N", a);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case D_CONST2:
|
||||||
|
sprint(str, "$%d-%d", a->offset, a->offset2);
|
||||||
|
break;
|
||||||
|
|
||||||
case D_SHIFT:
|
case D_SHIFT:
|
||||||
v = a->offset;
|
v = a->offset;
|
||||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||||
|
|
@ -224,6 +229,7 @@ Rconv(Fmt *fp)
|
||||||
sprint(str, "GOK-reglist");
|
sprint(str, "GOK-reglist");
|
||||||
switch(a->type) {
|
switch(a->type) {
|
||||||
case D_CONST:
|
case D_CONST:
|
||||||
|
case D_CONST2:
|
||||||
if(a->reg != NREG)
|
if(a->reg != NREG)
|
||||||
break;
|
break;
|
||||||
if(a->sym != S)
|
if(a->sym != S)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,31 @@
|
||||||
|
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
|
|
||||||
|
int32
|
||||||
|
argsize(void)
|
||||||
|
{
|
||||||
|
Type *t;
|
||||||
|
int32 s;
|
||||||
|
|
||||||
|
//print("t=%T\n", thisfn);
|
||||||
|
s = 0;
|
||||||
|
for(t=thisfn->down; t!=T; t=t->down) {
|
||||||
|
switch(t->etype) {
|
||||||
|
case TVOID:
|
||||||
|
break;
|
||||||
|
case TDOT:
|
||||||
|
s += 64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
s = align(s, t, Aarg1);
|
||||||
|
s = align(s, t, Aarg2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//print(" %d %T\n", s, t);
|
||||||
|
}
|
||||||
|
return (s+7) & ~7;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
codgen(Node *n, Node *nn)
|
codgen(Node *n, Node *nn)
|
||||||
{
|
{
|
||||||
|
|
@ -53,6 +78,9 @@ codgen(Node *n, Node *nn)
|
||||||
}
|
}
|
||||||
nearln = nn->lineno;
|
nearln = nn->lineno;
|
||||||
gpseudo(ATEXT, n1->sym, nodconst(stkoff));
|
gpseudo(ATEXT, n1->sym, nodconst(stkoff));
|
||||||
|
p->to.type = D_CONST2;
|
||||||
|
p->to.offset2 = argsize();
|
||||||
|
|
||||||
sp = p;
|
sp = p;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -313,7 +341,7 @@ loop:
|
||||||
|
|
||||||
patch(spc, pc);
|
patch(spc, pc);
|
||||||
gen(l->right->right); /* inc */
|
gen(l->right->right); /* inc */
|
||||||
patch(sp, pc);
|
patch(sp, pc);
|
||||||
if(l->left != Z) { /* test */
|
if(l->left != Z) { /* test */
|
||||||
bcomplex(l->left, Z);
|
bcomplex(l->left, Z);
|
||||||
patch(p, breakpc);
|
patch(p, breakpc);
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,7 @@ loop:
|
||||||
if(vs < 0) {
|
if(vs < 0) {
|
||||||
gopcode(OAS, &nod1, Z, &nod1);
|
gopcode(OAS, &nod1, Z, &nod1);
|
||||||
gopcode(OSUB, &nod1, nodconst(0), nn);
|
gopcode(OSUB, &nod1, nodconst(0), nn);
|
||||||
} else
|
} else
|
||||||
gopcode(OAS, &nod1, Z, nn);
|
gopcode(OAS, &nod1, Z, nn);
|
||||||
regfree(&nod1);
|
regfree(&nod1);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -649,6 +649,13 @@ zaddr(char *bp, Adr *a, int s)
|
||||||
case D_PSR:
|
case D_PSR:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case D_CONST2:
|
||||||
|
l = a->offset2;
|
||||||
|
bp[0] = l;
|
||||||
|
bp[1] = l>>8;
|
||||||
|
bp[2] = l>>16;
|
||||||
|
bp[3] = l>>24;
|
||||||
|
bp += 4; // fall through
|
||||||
case D_OREG:
|
case D_OREG:
|
||||||
case D_CONST:
|
case D_CONST:
|
||||||
case D_BRANCH:
|
case D_BRANCH:
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,10 @@ enum as
|
||||||
AB,
|
AB,
|
||||||
ABL,
|
ABL,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not reorder or fragment the conditional branch
|
* Do not reorder or fragment the conditional branch
|
||||||
* opcodes, or the predication code will break
|
* opcodes, or the predication code will break
|
||||||
*/
|
*/
|
||||||
ABEQ,
|
ABEQ,
|
||||||
ABNE,
|
ABNE,
|
||||||
ABCS,
|
ABCS,
|
||||||
|
|
@ -186,6 +186,22 @@ enum as
|
||||||
#define C_FBIT (1<<7) /* psr flags-only */
|
#define C_FBIT (1<<7) /* psr flags-only */
|
||||||
#define C_UBIT (1<<7) /* up bit */
|
#define C_UBIT (1<<7) /* up bit */
|
||||||
|
|
||||||
|
#define C_SCOND_EQ 0
|
||||||
|
#define C_SCOND_NE 1
|
||||||
|
#define C_SCOND_HS 2
|
||||||
|
#define C_SCOND_LO 3
|
||||||
|
#define C_SCOND_MI 4
|
||||||
|
#define C_SCOND_PL 5
|
||||||
|
#define C_SCOND_VS 6
|
||||||
|
#define C_SCOND_VC 7
|
||||||
|
#define C_SCOND_HI 8
|
||||||
|
#define C_SCOND_LS 9
|
||||||
|
#define C_SCOND_GE 10
|
||||||
|
#define C_SCOND_LT 11
|
||||||
|
#define C_SCOND_GT 12
|
||||||
|
#define C_SCOND_LE 13
|
||||||
|
#define C_SCOND_N 15
|
||||||
|
|
||||||
/* type/name */
|
/* type/name */
|
||||||
#define D_GOK 0
|
#define D_GOK 0
|
||||||
#define D_NONE 1
|
#define D_NONE 1
|
||||||
|
|
@ -209,6 +225,7 @@ enum as
|
||||||
#define D_ADDR (D_NONE+22)
|
#define D_ADDR (D_NONE+22)
|
||||||
|
|
||||||
#define D_SBIG (D_NONE+23)
|
#define D_SBIG (D_NONE+23)
|
||||||
|
#define D_CONST2 (D_NONE+24)
|
||||||
|
|
||||||
/* name */
|
/* name */
|
||||||
#define D_EXTERN (D_NONE+3)
|
#define D_EXTERN (D_NONE+3)
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ struct Adr
|
||||||
uchar index; // not used on arm, required by ld/go.c
|
uchar index; // not used on arm, required by ld/go.c
|
||||||
char reg;
|
char reg;
|
||||||
char name;
|
char name;
|
||||||
|
int32 offset2; // argsize
|
||||||
char class;
|
char class;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ Pconv(Fmt *fp)
|
||||||
switch(a) {
|
switch(a) {
|
||||||
default:
|
default:
|
||||||
s = str;
|
s = str;
|
||||||
s += sprint(s, "(%ld)", p->line);
|
s += sprint(s, "(%d)", p->line);
|
||||||
if(p->reg == NREG)
|
if(p->reg == NREG)
|
||||||
sprint(s, " %A%C %D,%D",
|
sprint(s, " %A%C %D,%D",
|
||||||
a, p->scond, &p->from, &p->to);
|
a, p->scond, &p->from, &p->to);
|
||||||
|
|
@ -76,23 +76,23 @@ Pconv(Fmt *fp)
|
||||||
|
|
||||||
case ASWPW:
|
case ASWPW:
|
||||||
case ASWPBU:
|
case ASWPBU:
|
||||||
sprint(str, "(%ld) %A%C R%d,%D,%D",
|
sprint(str, "(%d) %A%C R%d,%D,%D",
|
||||||
p->line, a, p->scond, p->reg, &p->from, &p->to);
|
p->line, a, p->scond, p->reg, &p->from, &p->to);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ADATA:
|
case ADATA:
|
||||||
case AINIT:
|
case AINIT:
|
||||||
case ADYNT:
|
case ADYNT:
|
||||||
sprint(str, "(%ld) %A%C %D/%d,%D",
|
sprint(str, "(%d) %A%C %D/%d,%D",
|
||||||
p->line, a, p->scond, &p->from, p->reg, &p->to);
|
p->line, a, p->scond, &p->from, p->reg, &p->to);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AWORD:
|
case AWORD:
|
||||||
sprint(str, "WORD %ld", p->to.offset);
|
sprint(str, "WORD %x", p->to.offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ADWORD:
|
case ADWORD:
|
||||||
sprint(str, "DWORD %ld %ld", p->from.offset, p->to.offset);
|
sprint(str, "DWORD %x %x", p->from.offset, p->to.offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return fmtstrcpy(fp, str);
|
return fmtstrcpy(fp, str);
|
||||||
|
|
@ -178,13 +178,17 @@ Dconv(Fmt *fp)
|
||||||
sprint(str, "$%N(R%d)", a, a->reg);
|
sprint(str, "$%N(R%d)", a, a->reg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case D_CONST2:
|
||||||
|
sprint(str, "$%d-%d", a->offset, a->offset2);
|
||||||
|
break;
|
||||||
|
|
||||||
case D_SHIFT:
|
case D_SHIFT:
|
||||||
v = a->offset;
|
v = a->offset;
|
||||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||||
if(v & (1<<4))
|
if(v & (1<<4))
|
||||||
sprint(str, "R%ld%c%cR%ld", v&15, op[0], op[1], (v>>8)&15);
|
sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
|
||||||
else
|
else
|
||||||
sprint(str, "R%ld%c%c%ld", v&15, op[0], op[1], (v>>7)&31);
|
sprint(str, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31);
|
||||||
if(a->reg != NREG)
|
if(a->reg != NREG)
|
||||||
sprint(str+strlen(str), "(R%d)", a->reg);
|
sprint(str+strlen(str), "(R%d)", a->reg);
|
||||||
break;
|
break;
|
||||||
|
|
@ -262,9 +266,9 @@ Dconv(Fmt *fp)
|
||||||
sprint(str, "%.5lux(BRANCH)", v);
|
sprint(str, "%.5lux(BRANCH)", v);
|
||||||
} else
|
} else
|
||||||
if(a->sym != S)
|
if(a->sym != S)
|
||||||
sprint(str, "%s+%ld(APC)", a->sym->name, a->offset);
|
sprint(str, "%s+%d(APC)", a->sym->name, a->offset);
|
||||||
else
|
else
|
||||||
sprint(str, "%ld(APC)", a->offset);
|
sprint(str, "%d(APC)", a->offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_FCONST:
|
case D_FCONST:
|
||||||
|
|
@ -293,35 +297,35 @@ Nconv(Fmt *fp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_NONE:
|
case D_NONE:
|
||||||
sprint(str, "%ld", a->offset);
|
sprint(str, "%d", a->offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_EXTERN:
|
case D_EXTERN:
|
||||||
if(s == S)
|
if(s == S)
|
||||||
sprint(str, "%ld(SB)", a->offset);
|
sprint(str, "%d(SB)", a->offset);
|
||||||
else
|
else
|
||||||
sprint(str, "%s+%ld(SB)", s->name, a->offset);
|
sprint(str, "%s+%d(SB)", s->name, a->offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_STATIC:
|
case D_STATIC:
|
||||||
if(s == S)
|
if(s == S)
|
||||||
sprint(str, "<>+%ld(SB)", a->offset);
|
sprint(str, "<>+%d(SB)", a->offset);
|
||||||
else
|
else
|
||||||
sprint(str, "%s<>+%ld(SB)", s->name, a->offset);
|
sprint(str, "%s<>+%d(SB)", s->name, a->offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_AUTO:
|
case D_AUTO:
|
||||||
if(s == S)
|
if(s == S)
|
||||||
sprint(str, "%ld(SP)", a->offset);
|
sprint(str, "%d(SP)", a->offset);
|
||||||
else
|
else
|
||||||
sprint(str, "%s-%ld(SP)", s->name, -a->offset);
|
sprint(str, "%s-%d(SP)", s->name, -a->offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_PARAM:
|
case D_PARAM:
|
||||||
if(s == S)
|
if(s == S)
|
||||||
sprint(str, "%ld(FP)", a->offset);
|
sprint(str, "%d(FP)", a->offset);
|
||||||
else
|
else
|
||||||
sprint(str, "%s+%ld(FP)", s->name, a->offset);
|
sprint(str, "%s+%d(FP)", s->name, a->offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return fmtstrcpy(fp, str);
|
return fmtstrcpy(fp, str);
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ noops(void)
|
||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
|
|
||||||
pmorestack = P;
|
pmorestack = P;
|
||||||
symmorestack = lookup("sys·morestack", 0);
|
symmorestack = lookup("sys·morestackx", 0);
|
||||||
|
|
||||||
if(symmorestack->type == STEXT)
|
if(symmorestack->type == STEXT)
|
||||||
for(p = firstp; p != P; p = p->link) {
|
for(p = firstp; p != P; p = p->link) {
|
||||||
|
|
@ -342,8 +342,7 @@ noops(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(p->reg & NOSPLIT) {
|
if(p->reg & NOSPLIT) {
|
||||||
if(1) {
|
|
||||||
q1 = prg();
|
q1 = prg();
|
||||||
q1->as = AMOVW;
|
q1->as = AMOVW;
|
||||||
q1->scond |= C_WBIT;
|
q1->scond |= C_WBIT;
|
||||||
|
|
@ -355,61 +354,78 @@ noops(void)
|
||||||
q1->to.reg = REGSP;
|
q1->to.reg = REGSP;
|
||||||
q1->link = p->link;
|
q1->link = p->link;
|
||||||
p->link = q1;
|
p->link = q1;
|
||||||
} else { // !NOSPLIT
|
} else if (autosize < StackBig) {
|
||||||
// split stack check
|
// split stack check for small functions
|
||||||
if(autosize < StackBig) {
|
// MOVW (REGG), R1
|
||||||
p = appendp(p); // load G.stackguard into R1
|
// CMP R1, $-autosize(SP)
|
||||||
p->as = AMOVW;
|
// MOVW.W.LT R14,$-autosize(SP)
|
||||||
p->from.type = D_OREG;
|
// MOVW.W.GE R14,$-4(SP)
|
||||||
p->from.reg = REGG;
|
// MOVW.GE $(args << 24 | autosize), R1
|
||||||
p->to.type = D_REG;
|
// BL.GE callmorestack(SB)
|
||||||
p->to.reg = 1;
|
|
||||||
|
|
||||||
p = appendp(p);
|
// TODO(kaib): double check we allocate autosize after
|
||||||
p->as = ACMP;
|
// stack has been split
|
||||||
p->from.type = D_REG;
|
// TODO(kaib): add error in case autosize doesn't pack
|
||||||
p->from.reg = 1;
|
// TODO(kaib): add more trampolines
|
||||||
p->from.offset = -autosize;
|
// TODO(kaib): put stackguard in register
|
||||||
p->reg = REGSP;
|
// TODO(kaib): add support for -K and underflow detection
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(kaib): Optimize the heck out of this
|
p = appendp(p); // load G.stackguard into R1
|
||||||
p = appendp(p); // store autosize in M.morearg
|
|
||||||
p->as = AMOVW;
|
p->as = AMOVW;
|
||||||
p->from.type = D_CONST;
|
p->from.type = D_OREG;
|
||||||
if(autosize+160 > 4096)
|
p->from.reg = REGG;
|
||||||
p->from.offset = (autosize+160) & ~7LL;
|
|
||||||
p->to.type = D_REG;
|
p->to.type = D_REG;
|
||||||
p->to.reg = REGTMP;
|
p->to.reg = 1;
|
||||||
|
|
||||||
p = appendp(p);
|
p = appendp(p);
|
||||||
p->as = AMOVW;
|
p->as = ACMP;
|
||||||
p->from.type = D_REG;
|
p->from.type = D_REG;
|
||||||
p->from.reg = REGTMP;
|
p->from.reg = 1;
|
||||||
p->to.type = D_OREG;
|
p->from.offset = -autosize;
|
||||||
p->to.reg = REGM;
|
p->reg = REGSP;
|
||||||
p->to.offset = 4;
|
|
||||||
|
|
||||||
p = appendp(p);
|
p = appendp(p);
|
||||||
p->as = AMOVW;
|
p->as = AMOVW;
|
||||||
|
p->scond = C_SCOND_GE | C_WBIT;
|
||||||
|
p->from.type = D_REG;
|
||||||
|
p->from.reg = REGLINK;
|
||||||
|
p->to.type = D_OREG;
|
||||||
|
p->to.offset = -autosize;
|
||||||
|
p->to.reg = REGSP;
|
||||||
|
|
||||||
|
p = appendp(p);
|
||||||
|
p->as = AMOVW;
|
||||||
|
p->scond = C_SCOND_LT | C_WBIT;
|
||||||
|
p->from.type = D_REG;
|
||||||
|
p->from.reg = REGLINK;
|
||||||
|
p->to.type = D_OREG;
|
||||||
|
p->to.offset = -4;
|
||||||
|
p->to.reg = REGSP;
|
||||||
|
|
||||||
|
p = appendp(p); // packs args and autosize
|
||||||
|
p->as = AMOVW;
|
||||||
|
p->scond = C_SCOND_LT;
|
||||||
p->from.type = D_CONST;
|
p->from.type = D_CONST;
|
||||||
// p->from.offset = curtext->to.offset2;
|
// top 8 bits are arg count, lower 24 bits number of 4 byte
|
||||||
|
// words
|
||||||
|
p->from.offset =
|
||||||
|
(curtext->to.offset2 & ~7) << 21 |
|
||||||
|
(autosize & ~7) >> 3;
|
||||||
p->to.type = D_REG;
|
p->to.type = D_REG;
|
||||||
p->to.reg = REGTMP;
|
p->to.reg = 1;
|
||||||
|
|
||||||
p = appendp(p);
|
p = appendp(p);
|
||||||
p->as = AMOVW;
|
p->as = ABL;
|
||||||
p->from.type = D_REG;
|
p->scond = C_SCOND_LT;
|
||||||
p->from.reg = REGTMP;
|
p->to.type = D_BRANCH;
|
||||||
p->to.type = D_OREG;
|
p->to.sym = symmorestack;
|
||||||
p->to.reg = REGM;
|
p->cond = pmorestack;
|
||||||
p->to.offset = 8;
|
} else { // > StackBig
|
||||||
|
// MOVW.W R14,$-4(SP)
|
||||||
// p = appendp(p);
|
// MOVW $(args << 24 | autosize), R1
|
||||||
// p->as = ABL;
|
// BL callmorestack(SB)
|
||||||
// p->to.type = D_BRANCH;
|
// TODO(kaib): Fix large stacks, don't use packing
|
||||||
// p->to.sym = symmorestack;
|
diag("StackBig broken");
|
||||||
// p->cond = pmorestack;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -803,7 +819,7 @@ noops(void)
|
||||||
p->link = q;
|
p->link = q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(seenthumb && !thumb && p->to.type == D_OREG && p->to.reg == REGLINK){
|
if(seenthumb && !thumb && p->to.type == D_OREG && p->to.reg == REGLINK){
|
||||||
// print("warn %s: b (R%d) assuming a return\n", curtext->from.sym->name, p->to.reg);
|
// print("warn %s: b (R%d) assuming a return\n", curtext->from.sym->name, p->to.reg);
|
||||||
p->as = ABXRET;
|
p->as = ABXRET;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -546,6 +546,8 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
|
||||||
c++;
|
c++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case D_CONST2:
|
||||||
|
a->offset2 = Bget4(f); // fall through
|
||||||
case D_BRANCH:
|
case D_BRANCH:
|
||||||
case D_OREG:
|
case D_OREG:
|
||||||
case D_CONST:
|
case D_CONST:
|
||||||
|
|
|
||||||
|
|
@ -87,12 +87,12 @@ fninc(Sym *s)
|
||||||
return 4;
|
return 4;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fnpinc(Sym *s)
|
fnpinc(Sym *s)
|
||||||
{
|
{
|
||||||
if(!s->fnptr){ // a simplified case BX O(R) -> BL O(R)
|
if(!s->fnptr){ // a simplified case BX O(R) -> BL O(R)
|
||||||
|
|
@ -318,7 +318,7 @@ span(void)
|
||||||
else
|
else
|
||||||
m = 2;
|
m = 2;
|
||||||
p->align = 0;
|
p->align = 0;
|
||||||
}
|
}
|
||||||
if(p->align){
|
if(p->align){
|
||||||
if((p->align == 4 && (c&3)) || (p->align == 2 && !(c&3))){
|
if((p->align == 4 && (c&3)) || (p->align == 2 && !(c&3))){
|
||||||
if(ispad(op)){
|
if(ispad(op)){
|
||||||
|
|
@ -374,9 +374,9 @@ span(void)
|
||||||
// print("%d bytes removed (padding)\n", d);
|
// print("%d bytes removed (padding)\n", d);
|
||||||
c -= d;
|
c -= d;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(debug['t']) {
|
if(debug['t']) {
|
||||||
/*
|
/*
|
||||||
* add strings to text segment
|
* add strings to text segment
|
||||||
*/
|
*/
|
||||||
c = rnd(c, 8);
|
c = rnd(c, 8);
|
||||||
|
|
@ -391,7 +391,7 @@ span(void)
|
||||||
c += v;
|
c += v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c = rnd(c, 8);
|
c = rnd(c, 8);
|
||||||
|
|
||||||
setext = lookup("etext", 0);
|
setext = lookup("etext", 0);
|
||||||
|
|
@ -726,6 +726,7 @@ aclass(Adr *a)
|
||||||
return C_FCON;
|
return C_FCON;
|
||||||
|
|
||||||
case D_CONST:
|
case D_CONST:
|
||||||
|
case D_CONST2:
|
||||||
switch(a->name) {
|
switch(a->name) {
|
||||||
|
|
||||||
case D_NONE:
|
case D_NONE:
|
||||||
|
|
@ -1072,7 +1073,7 @@ buildop(void)
|
||||||
oprange[AMOVFD] = oprange[r];
|
oprange[AMOVFD] = oprange[r];
|
||||||
oprange[AMOVDF] = oprange[r];
|
oprange[AMOVDF] = oprange[r];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACMPF:
|
case ACMPF:
|
||||||
oprange[ACMPD] = oprange[r];
|
oprange[ACMPD] = oprange[r];
|
||||||
break;
|
break;
|
||||||
|
|
@ -1246,7 +1247,7 @@ asmdyn()
|
||||||
t += 4;
|
t += 4;
|
||||||
t += sput(s->name);
|
t += sput(s->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
la = 0;
|
la = 0;
|
||||||
r = &rels;
|
r = &rels;
|
||||||
n = r->n;
|
n = r->n;
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,11 @@ addr(Biobuf *bp)
|
||||||
case D_PSR:
|
case D_PSR:
|
||||||
case D_FPCR:
|
case D_FPCR:
|
||||||
break;
|
break;
|
||||||
|
case D_CONST2:
|
||||||
|
Bgetc(bp);
|
||||||
|
Bgetc(bp);
|
||||||
|
Bgetc(bp);
|
||||||
|
Bgetc(bp); // fall through
|
||||||
case D_OREG:
|
case D_OREG:
|
||||||
case D_CONST:
|
case D_CONST:
|
||||||
case D_BRANCH:
|
case D_BRANCH:
|
||||||
|
|
|
||||||
|
|
@ -3,88 +3,80 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
TEXT _rt0_arm(SB),7,$0
|
TEXT _rt0_arm(SB),7,$0
|
||||||
// copy arguments forward on an even stack
|
MOVW $setR12(SB), R12
|
||||||
// MOVW $0(SP), R0
|
|
||||||
// MOVL 0(SP), R1 // argc
|
|
||||||
// LEAL 4(SP), R1 // argv
|
|
||||||
// SUBL $128, SP // plenty of scratch
|
|
||||||
// ANDL $~7, SP
|
|
||||||
// MOVL AX, 120(SP) // save argc, argv away
|
|
||||||
// MOVL BX, 124(SP)
|
|
||||||
|
|
||||||
|
// copy arguments forward on an even stack
|
||||||
|
MOVW 0(SP), R0 // argc
|
||||||
|
MOVW 4(SP), R1 // argv
|
||||||
|
SUB $128, SP // plenty of scratch
|
||||||
|
AND $~7, SP
|
||||||
|
MOVW R0, 120(SP) // save argc, argv away
|
||||||
|
MOVW R1, 124(SP)
|
||||||
|
|
||||||
// // write "go386\n"
|
// set up m and g registers
|
||||||
// PUSHL $6
|
// g is R10, m is R9
|
||||||
// PUSHL $hello(SB)
|
MOVW $g0(SB), R10
|
||||||
// PUSHL $1
|
MOVW $m0(SB), R9
|
||||||
// CALL sys·write(SB)
|
|
||||||
// POPL AX
|
|
||||||
// POPL AX
|
|
||||||
// POPL AX
|
|
||||||
|
|
||||||
|
// save m->g0 = g0
|
||||||
|
MOVW R10, 0(R9)
|
||||||
|
|
||||||
// CALL ldt0setup(SB)
|
// create istack out of the OS stack
|
||||||
|
MOVW $(-8192+104)(SP), R0
|
||||||
|
MOVW R0, 0(R10) // 0(g) is stack limit (w 104b guard)
|
||||||
|
MOVW SP, 4(R10) // 4(g) is base
|
||||||
|
BL emptyfunc(SB) // fault if stack check is wrong
|
||||||
|
|
||||||
// set up %fs to refer to that ldt entry
|
BL check(SB)
|
||||||
// MOVL $(7*8+7), AX
|
|
||||||
// MOVW AX, FS
|
|
||||||
|
|
||||||
// // store through it, to make sure it works
|
// saved argc, argv
|
||||||
// MOVL $0x123, 0(FS)
|
MOVW 120(SP), R0
|
||||||
// MOVL tls0(SB), AX
|
MOVW R0, 0(SP)
|
||||||
// CMPL AX, $0x123
|
MOVW 124(SP), R0
|
||||||
// JEQ ok
|
MOVW R0, 4(SP)
|
||||||
// MOVL AX, 0
|
BL args(SB)
|
||||||
// ok:
|
BL osinit(SB)
|
||||||
|
BL schedinit(SB)
|
||||||
|
|
||||||
// // set up m and g "registers"
|
// create a new goroutine to start program
|
||||||
// // g is 0(FS), m is 4(FS)
|
MOVW $mainstart(SB), R0
|
||||||
// LEAL g0(SB), CX
|
MOVW.W R0, -4(SP)
|
||||||
// MOVL CX, 0(FS)
|
MOVW $8, R0
|
||||||
// LEAL m0(SB), AX
|
MOVW.W R0, -4(SP)
|
||||||
// MOVL AX, 4(FS)
|
MOVW $0, R0
|
||||||
|
MOVW.W R0, -4(SP) // push $0 as guard
|
||||||
|
BL sys·newproc(SB)
|
||||||
|
MOVW $12(SP), SP // pop args and LR
|
||||||
|
|
||||||
// // save m->g0 = g0
|
// start this M
|
||||||
// MOVL CX, 0(AX)
|
BL mstart(SB)
|
||||||
|
|
||||||
// // create istack out of the OS stack
|
MOVW $0, R0
|
||||||
// LEAL (-8192+104)(SP), AX // TODO: 104?
|
|
||||||
// MOVL AX, 0(CX) // 8(g) is stack limit (w 104b guard)
|
|
||||||
// MOVL SP, 4(CX) // 12(g) is base
|
|
||||||
// CALL emptyfunc(SB) // fault if stack check is wrong
|
|
||||||
|
|
||||||
// // convention is D is always cleared
|
|
||||||
// CLD
|
|
||||||
|
|
||||||
// CALL check(SB)
|
|
||||||
|
|
||||||
// // saved argc, argv
|
|
||||||
// MOVL 120(SP), AX
|
|
||||||
// MOVL AX, 0(SP)
|
|
||||||
// MOVL 124(SP), AX
|
|
||||||
// MOVL AX, 4(SP)
|
|
||||||
// CALL args(SB)
|
|
||||||
// CALL osinit(SB)
|
|
||||||
// CALL schedinit(SB)
|
|
||||||
|
|
||||||
// // create a new goroutine to start program
|
|
||||||
// PUSHL $mainstart(SB) // entry
|
|
||||||
// PUSHL $8 // arg size
|
|
||||||
// CALL sys·newproc(SB)
|
|
||||||
// POPL AX
|
|
||||||
// POPL AX
|
|
||||||
|
|
||||||
// // start this M
|
|
||||||
// CALL mstart(SB)
|
|
||||||
|
|
||||||
BL main·main(SB)
|
|
||||||
MOVW $99, R0
|
|
||||||
SWI $0x00900001
|
SWI $0x00900001
|
||||||
|
B _dep_dummy(SB) // Never reached
|
||||||
|
|
||||||
|
|
||||||
|
TEXT mainstart(SB),7,$0
|
||||||
|
BL main·init(SB)
|
||||||
|
BL initdone(SB)
|
||||||
|
BL main·main(SB)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW.W R0, -4(SP)
|
||||||
|
MOVW.W R14, -4(SP) // Push link as well
|
||||||
|
BL exit(SB)
|
||||||
|
MOVW $8(SP), SP // pop args and LR
|
||||||
|
RET
|
||||||
|
|
||||||
// TODO(kaib): remove these once linker works properly
|
// TODO(kaib): remove these once linker works properly
|
||||||
// pull in dummy dependencies
|
// pull in dummy dependencies
|
||||||
// TEXT _dep_dummy(SB),7,$0
|
TEXT _dep_dummy(SB),7,$0
|
||||||
// BL sys·morestack(SB)
|
BL sys·morestack(SB)
|
||||||
|
BL sys·morestackx(SB)
|
||||||
|
BL _div(SB)
|
||||||
|
BL _divu(SB)
|
||||||
|
BL _mod(SB)
|
||||||
|
BL _modu(SB)
|
||||||
|
BL _modu(SB)
|
||||||
|
|
||||||
|
|
||||||
TEXT breakpoint(SB),7,$0
|
TEXT breakpoint(SB),7,$0
|
||||||
|
|
@ -114,33 +106,38 @@ TEXT gosave(SB), 7, $0
|
||||||
// support for morestack
|
// support for morestack
|
||||||
|
|
||||||
// return point when leaving new stack.
|
// return point when leaving new stack.
|
||||||
// save AX, jmp to lesstack to switch back
|
// save R0, jmp to lesstack to switch back
|
||||||
TEXT retfromnewstack(SB),7,$0
|
TEXT retfromnewstack(SB),7,$0
|
||||||
BL abort(SB)
|
MOVW R0,12(R9) // m->cret
|
||||||
// MOVL 4(FS), BX // m
|
B lessstack(SB)
|
||||||
// MOVL AX, 12(BX) // save AX in m->cret
|
|
||||||
// JMP lessstack(SB)
|
|
||||||
|
|
||||||
// gogo, returning 2nd arg instead of 1
|
// gogo, returning 2nd arg instead of 1
|
||||||
TEXT gogoret(SB), 7, $0
|
TEXT gogoret(SB), 7, $0
|
||||||
BL abort(SB)
|
MOVW 8(SP), R0 // return 2nd arg
|
||||||
// MOVL 8(SP), AX // return 2nd arg
|
MOVW 4(SP), R1 // gobuf
|
||||||
// MOVL 4(SP), BX // gobuf
|
MOVW 0(R1), SP // restore SP
|
||||||
// MOVL 0(BX), SP // restore SP
|
MOVW 4(R1), PC // restore PC
|
||||||
// MOVL 4(BX), BX
|
|
||||||
// MOVL BX, 0(SP) // put PC on the stack
|
|
||||||
// RET
|
|
||||||
|
|
||||||
TEXT setspgoto(SB), 7, $0
|
TEXT setspgoto(SB), 7, $0
|
||||||
BL abort(SB)
|
MOVW 4(SP), R0 // SP
|
||||||
// MOVL 4(SP), AX // SP
|
MOVW 8(SP), R1 // fn to call
|
||||||
// MOVL 8(SP), BX // fn to call
|
MOVW 12(SP), R2 // fn to return into
|
||||||
// MOVL 12(SP), CX // fn to return
|
MOVW R2, R14 // restore LR
|
||||||
// MOVL AX, SP
|
MOVW R0, SP
|
||||||
// PUSHL CX
|
MOVW R1, PC // goto
|
||||||
// JMP BX
|
|
||||||
// POPL AX // not reached
|
// Optimization to make inline stack splitting code smaller
|
||||||
// RET
|
// R0 is original first argument
|
||||||
|
// R1 is arg_num << 24 | autosize >> 3
|
||||||
|
TEXT sys·morestackx(SB), 7, $0
|
||||||
|
MOVW R0, 4(SP) // Save arg0
|
||||||
|
MOVW R1<<8, R2
|
||||||
|
MOVW R2>>5, R2
|
||||||
|
MOVW R2, 4(R10) // autooffset into g
|
||||||
|
MOVW R1>>24, R2
|
||||||
|
MOVW R2<<3, R2
|
||||||
|
MOVW R2, 8(R10) // argsize into g
|
||||||
|
B sys·morestack(SB)
|
||||||
|
|
||||||
// bool cas(int32 *val, int32 old, int32 new)
|
// bool cas(int32 *val, int32 old, int32 new)
|
||||||
// Atomically:
|
// Atomically:
|
||||||
|
|
@ -149,18 +146,26 @@ TEXT setspgoto(SB), 7, $0
|
||||||
// return 1;
|
// return 1;
|
||||||
// }else
|
// }else
|
||||||
// return 0;
|
// return 0;
|
||||||
TEXT cas(SB), 7, $0
|
#define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12)
|
||||||
BL abort(SB)
|
#define STREX(a,v,r) WORD $(0xe<<28|0x01800f90 | (a)<<16 | (r)<<12 | (v)<<0)
|
||||||
// MOVL 4(SP), BX
|
|
||||||
// MOVL 8(SP), AX
|
TEXT cas+0(SB),0,$12 /* r0 holds p */
|
||||||
// MOVL 12(SP), CX
|
MOVW ov+4(FP), R1
|
||||||
// LOCK
|
MOVW nv+8(FP), R2
|
||||||
// CMPXCHGL CX, 0(BX)
|
spin:
|
||||||
// JZ 3(PC)
|
/* LDREX 0(R0),R3 */
|
||||||
// MOVL $0, AX
|
LDREX(0,3)
|
||||||
// RET
|
CMP.S R3, R1
|
||||||
// MOVL $1, AX
|
BNE fail
|
||||||
// RET
|
/* STREX 0(R0),R2,R4 */
|
||||||
|
STREX(0,2,4)
|
||||||
|
CMP.S $0, R4
|
||||||
|
BNE spin
|
||||||
|
MOVW $1, R0
|
||||||
|
RET
|
||||||
|
fail:
|
||||||
|
MOVW $0, R0
|
||||||
|
RET
|
||||||
|
|
||||||
// void jmpdefer(fn, sp);
|
// void jmpdefer(fn, sp);
|
||||||
// called from deferreturn.
|
// called from deferreturn.
|
||||||
|
|
@ -200,6 +205,10 @@ TEXT sys·setcallerpc+0(SB),7,$0
|
||||||
// MOVL BX, -4(AX) // set calling pc
|
// MOVL BX, -4(AX) // set calling pc
|
||||||
// RET
|
// RET
|
||||||
|
|
||||||
TEXT abort(SB),7,$0
|
TEXT emptyfunc(SB),0,$0
|
||||||
WORD $0
|
RET
|
||||||
|
|
||||||
|
TEXT abort(SB),7,$0
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW (R0), R1
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue