mirror of
https://github.com/golang/go
synced 2024-11-22 18:14:42 -07:00
code generation
R=r OCL=21146 CL=21146
This commit is contained in:
parent
937ac13f26
commit
719b088697
@ -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,10 +317,11 @@ 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(&n2);
|
||||||
regfree(&n1);
|
regfree(&n1);
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user