1
0
mirror of https://github.com/golang/go synced 2024-11-26 00:17:58 -07:00

code generation

R=r
OCL=21146
CL=21146
This commit is contained in:
Ken Thompson 2008-12-13 16:41:47 -08:00
parent 937ac13f26
commit 719b088697
4 changed files with 75 additions and 109 deletions

View File

@ -9,7 +9,7 @@ cgen(Node *n, Node *res)
{ {
Node *nl, *nr, *r; Node *nl, *nr, *r;
Node n1, n2; Node n1, n2;
int a; int a, f;
Prog *p1, *p2, *p3; Prog *p1, *p2, *p3;
Addr addr; Addr addr;
@ -48,6 +48,36 @@ cgen(Node *n, Node *res)
goto ret; goto ret;
} }
if(res->ullman >= UINF)
goto gen;
f = 1; // gen thru register
switch(n->op) {
case OLITERAL:
if(isint[n->type->etype])
if(n->type->width <= 4)
f = 0;
break;
case OREGISTER:
f = 0;
break;
}
if(sudoaddable(res, n->type, &addr, &n1)) {
a = optoas(OAS, res->type);
if(f) {
regalloc(&n2, res->type, N);
cgen(n, &n2);
p1 = gins(a, &n2, N);
regfree(&n2);
} else
p1 = gins(a, n, N);
p1->to = addr;
regfree(&n1);
goto ret;
}
gen:
igen(res, &n1, N); igen(res, &n1, N);
cgen(n, &n1); cgen(n, &n1);
regfree(&n1); regfree(&n1);
@ -71,19 +101,20 @@ cgen(Node *n, Node *res)
goto ret; goto ret;
} }
if(sudoaddable(n, res->type, &addr)) { if(sudoaddable(n, res->type, &addr, &n1)) {
a = optoas(OAS, n->type); a = optoas(OAS, n->type);
if(res->op == OREGISTER) { if(res->op == OREGISTER) {
p1 = gins(a, N, res); p1 = gins(a, N, res);
p1->from = addr; p1->from = addr;
} else { } else {
regalloc(&n1, n->type, N); regalloc(&n2, n->type, &n1);
p1 = gins(a, N, &n1); p1 = gins(a, N, &n2);
p1->from = addr; p1->from = addr;
gins(a, &n1, res); gins(a, &n2, res);
regfree(&n1); regfree(&n2);
} }
return; regfree(&n1);
goto ret;
} }
switch(n->op) { switch(n->op) {
@ -173,10 +204,10 @@ cgen(Node *n, Node *res)
regfree(&n1); regfree(&n1);
break; break;
case OINDEXPTR:
case OINDEX:
case ODOT: case ODOT:
case ODOTPTR: case ODOTPTR:
case OINDEXPTR:
case OINDEX:
case OIND: case OIND:
igen(n, &n1, res); igen(n, &n1, res);
gmove(&n1, res); gmove(&n1, res);
@ -286,13 +317,14 @@ abop: // asymmetric binary
regalloc(&n1, nl->type, res); regalloc(&n1, nl->type, res);
cgen(nl, &n1); cgen(nl, &n1);
if(sudoaddable(nr, nl->type, &addr)) { if(sudoaddable(nr, nl->type, &addr, &n2)) {
p1 = gins(a, N, &n1); p1 = gins(a, N, &n1);
p1->from = addr; p1->from = addr;
gmove(&n1, res); gmove(&n1, res);
regfree(&n1); regfree(&n2);
goto ret; regfree(&n1);
} goto ret;
}
regalloc(&n2, nr->type, N); regalloc(&n2, nr->type, N);
cgen(nr, &n2); cgen(nr, &n2);

View File

@ -1165,15 +1165,10 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
gmove(dx, res); gmove(dx, res);
} }
/*
* this is hard because divide
* is done in a fixed numerator
* of combined DX:AX registers
*/
void void
cgen_div(int op, Node *nl, Node *nr, Node *res) cgen_div(int op, Node *nl, Node *nr, Node *res)
{ {
Node ax, dx, n3, tmpax, tmpdx; Node ax, dx;
int rax, rdx; int rax, rdx;
rax = reg[D_AX]; rax = reg[D_AX];
@ -1184,64 +1179,12 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
regalloc(&ax, nl->type, &ax); regalloc(&ax, nl->type, &ax);
regalloc(&dx, nl->type, &dx); regalloc(&dx, nl->type, &dx);
// clean out the AX register
if(rax && !samereg(res, &ax)) {
if(rdx && !samereg(res, &dx)) {
regalloc(&tmpdx, types[TINT64], N);
regalloc(&tmpax, types[TINT64], N);
regalloc(&n3, nl->type, N); // dest for div
gins(AMOVQ, &dx, &tmpdx);
gins(AMOVQ, &ax, &tmpax);
dodiv(op, nl, nr, &n3, &ax, &dx);
gins(AMOVQ, &tmpax, &ax);
gins(AMOVQ, &tmpdx, &dx);
gmove(&n3, res);
regfree(&tmpdx);
regfree(&tmpax);
regfree(&n3);
goto ret;
}
regalloc(&tmpax, types[TINT64], N);
regalloc(&n3, nl->type, N); // dest for div
gins(AMOVQ, &ax, &tmpax);
dodiv(op, nl, nr, &n3, &ax, &dx);
gins(AMOVQ, &tmpax, &ax);
gmove(&n3, res);
regfree(&tmpax);
regfree(&n3);
goto ret;
}
// clean out the DX register
if(rdx && !samereg(res, &dx)) {
regalloc(&tmpdx, types[TINT64], N);
regalloc(&n3, nl->type, N); // dest for div
gins(AMOVQ, &dx, &tmpdx);
dodiv(op, nl, nr, &n3, &ax, &dx);
gins(AMOVQ, &tmpdx, &dx);
gmove(&n3, res);
regfree(&tmpdx);
regfree(&n3);
goto ret;
}
dodiv(op, nl, nr, res, &ax, &dx); dodiv(op, nl, nr, res, &ax, &dx);
ret:
regfree(&ax); regfree(&ax);
regfree(&dx); regfree(&dx);
} }
/*
* this is hard because shift
* count is either constant
* or the CL register
*/
void void
cgen_shift(int op, Node *nl, Node *nr, Node *res) cgen_shift(int op, Node *nl, Node *nr, Node *res)
{ {
@ -1271,25 +1214,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
nodreg(&n1, types[TINT64], D_CX); nodreg(&n1, types[TINT64], D_CX);
regalloc(&n1, nr->type, &n1); regalloc(&n1, nr->type, &n1);
// clean out the CL register regalloc(&n2, nl->type, res);
if(rcl) {
regalloc(&n2, types[TINT64], N);
gins(AMOVQ, &n1, &n2);
regfree(&n1);
reg[D_CX] = 0;
if(samereg(res, &n1))
cgen_shift(op, nl, nr, &n2);
else
cgen_shift(op, nl, nr, res);
reg[D_CX] = rcl;
gins(AMOVQ, &n2, &n1);
regfree(&n2);
goto ret;
}
regalloc(&n2, nl->type, res); // can one shift the CL register
if(nl->ullman >= nr->ullman) { if(nl->ullman >= nr->ullman) {
cgen(nl, &n2); cgen(nl, &n2);
cgen(nr, &n1); cgen(nr, &n1);

View File

@ -199,7 +199,7 @@ void tempname(Node*, Type*);
Plist* newplist(void); Plist* newplist(void);
int isfat(Type*); int isfat(Type*);
void setmaxarg(Type*); void setmaxarg(Type*);
int sudoaddable(Node*, Type*, Addr*); int sudoaddable(Node*, Type*, Addr*, Node*);
/* /*
* list.c * list.c

View File

@ -113,7 +113,12 @@ ginit(void)
reg[i] = 0; reg[i] = 0;
for(i=D_X0; i<=D_X7; i++) for(i=D_X0; i<=D_X7; i++)
reg[i] = 0; reg[i] = 0;
reg[D_SP]++; reg[D_AX]++; // for divide
reg[D_CX]++; // for shift
reg[D_DI]++; // for movstring
reg[D_DX]++; // for divide
reg[D_SI]++; // for movstring
reg[D_SP]++; // for stack
} }
void void
@ -121,7 +126,12 @@ gclean(void)
{ {
int i; int i;
reg[D_SP]--; reg[D_AX]--; // for divide
reg[D_CX]--; // for shift
reg[D_DI]--; // for movstring
reg[D_DX]--; // for divide
reg[D_SI]--; // for movstring
reg[D_SP]--; // for stack
for(i=D_AX; i<=D_R15; i++) for(i=D_AX; i<=D_R15; i++)
if(reg[i]) if(reg[i])
yyerror("reg %R left allocated\n", i); yyerror("reg %R left allocated\n", i);
@ -1800,11 +1810,11 @@ dotoffset(Node *n, int *oary, Node **nn)
} }
int int
sudoaddable(Node *n, Type *t, Addr *a) sudoaddable(Node *n, Type *t, Addr *a, Node *reg)
{ {
int et, o, i; int et, o, i;
int oary[10]; int oary[10];
Node n1, n2, *nn; Node n1, *nn;
if(n->type == T || t == T) if(n->type == T || t == T)
return 0; return 0;
@ -1831,28 +1841,27 @@ sudoaddable(Node *n, Type *t, Addr *a)
return 0; return 0;
} }
regalloc(&n1, types[tptr], N); regalloc(reg, types[tptr], N);
n2 = n1; n1 = *reg;
n2.op = OINDREG; n1.op = OINDREG;
if(oary[0] >= 0) { if(oary[0] >= 0) {
agen(nn, &n1); agen(nn, reg);
n2.xoffset = oary[0]; n1.xoffset = oary[0];
} else { } else {
cgen(nn, &n1); cgen(nn, reg);
n2.xoffset = -(oary[0]+1); n1.xoffset = -(oary[0]+1);
} }
for(i=1; i<o; i++) { for(i=1; i<o; i++) {
if(oary[i] >= 0) if(oary[i] >= 0)
fatal("cant happen"); fatal("cant happen");
gins(AMOVQ, &n2, &n1); gins(AMOVQ, &n1, reg);
n2.xoffset = -(oary[i]+1); n1.xoffset = -(oary[i]+1);
} }
a->type = D_NONE; a->type = D_NONE;
a->index = D_NONE; a->index = D_NONE;
naddr(&n2, a); naddr(&n1, a);
regfree(&n1);
break; break;
} }
return 1; return 1;