Commit f7753f16 authored by Ken Thompson's avatar Ken Thompson

more code generation - mostly shift and multiply

SVN=121585
parent 181ad474
...@@ -9,7 +9,7 @@ cgen(Node *n, Node *res) ...@@ -9,7 +9,7 @@ cgen(Node *n, Node *res)
{ {
long lno; long lno;
Node *nl, *nr, *r; Node *nl, *nr, *r;
Node n1, tmp; Node n1, n2;
int a; int a;
Prog *p1, *p2, *p3; Prog *p1, *p2, *p3;
...@@ -113,8 +113,6 @@ cgen(Node *n, Node *res) ...@@ -113,8 +113,6 @@ cgen(Node *n, Node *res)
// asymmetric binary // asymmetric binary
case OSUB: case OSUB:
case OLSH:
case ORSH:
a = optoas(n->op, nl->type); a = optoas(n->op, nl->type);
goto abop; goto abop;
...@@ -240,6 +238,10 @@ cgen(Node *n, Node *res) ...@@ -240,6 +238,10 @@ cgen(Node *n, Node *res)
case ODIV: case ODIV:
cgen_div(n->op, nl, nr, res); cgen_div(n->op, nl, nr, res);
break; break;
case OLSH:
case ORSH:
cgen_shift(n->op, nl, nr, res);
break;
} }
goto ret; goto ret;
...@@ -251,26 +253,21 @@ sbop: // symmetric binary ...@@ -251,26 +253,21 @@ sbop: // symmetric binary
} }
abop: // asymmetric binary abop: // asymmetric binary
if(nr->addable) { if(nl->ullman >= nr->ullman) {
regalloc(&n1, nl->type, res);
cgen(nl, &n1);
regalloc(&n2, nr->type, N);
cgen(nr, &n2);
} else {
regalloc(&n2, nr->type, N);
cgen(nr, &n2);
regalloc(&n1, nl->type, res); regalloc(&n1, nl->type, res);
cgen(nl, &n1); cgen(nl, &n1);
gins(a, nr, &n1);
gmove(&n1, res);
regfree(&n1);
goto ret;
} }
gins(a, &n2, &n1);
tempname(&tmp, nr->type);
regalloc(&n1, nr->type, res);
cgen(nr, &n1);
gmove(&n1, &tmp);
regfree(&n1);
regalloc(&n1, nl->type, res);
cgen(nl, &n1);
gins(a, &tmp, &n1);
gmove(&n1, res); gmove(&n1, res);
regfree(&n1); regfree(&n1);
regfree(&n2);
goto ret; goto ret;
uop: // unary uop: // unary
...@@ -375,18 +372,16 @@ agen(Node *n, Node *res) ...@@ -375,18 +372,16 @@ agen(Node *n, Node *res)
// &a is in res // &a is in res
// i is in &n1 // i is in &n1
// w is width // w is width
if(issigned[n1.type->etype]) { nodconst(&n3, types[TINT64], w); // w/tint64
nodconst(&n3, types[TINT64], w); // w/tint64 if(issigned[n1.type->etype])
regalloc(&n2, types[TINT64], &n1); // i/int64 regalloc(&n2, types[TINT64], &n1); // i/int64
gmove(&n1, &n2); else
gins(optoas(OMUL, types[TINT64]), &n3, &n2); regalloc(&n2, types[TUINT64], &n1); // i/uint64
gins(optoas(OADD, types[tptr]), &n2, res); gmove(&n1, &n2);
regfree(&n1); gins(optoas(OMUL, types[TINT64]), &n3, &n2);
regfree(&n2); gins(optoas(OADD, types[tptr]), &n2, res);
break; regfree(&n1);
} regfree(&n2);
// unsigned multiply is a pain in the ass
fatal("agen: unsigned index");
break; break;
// case OIND: // case OIND:
......
...@@ -839,25 +839,32 @@ samereg(Node *a, Node *b) ...@@ -839,25 +839,32 @@ samereg(Node *a, Node *b)
return 1; return 1;
} }
/*
* 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 n1, n2, n3; Node n1, n2, n3;
int a, rax, rdx; int a, rax, rdx;
nodreg(&n1, types[TINT64], D_AX);
nodreg(&n2, types[TINT64], D_DX);
rax = reg[D_AX]; rax = reg[D_AX];
rdx = reg[D_DX]; rdx = reg[D_DX];
// hold down the DX:AX registers nodreg(&n1, types[TINT64], D_AX);
nodreg(&n2, types[TINT64], D_DX);
regalloc(&n1, nr->type, &n1); regalloc(&n1, nr->type, &n1);
regalloc(&n2, nr->type, &n2);
// clean out the AX register
if(rax && !samereg(res, &n1)) { if(rax && !samereg(res, &n1)) {
// clean out the AX register
regalloc(&n3, types[TINT64], N); regalloc(&n3, types[TINT64], N);
gins(AMOVQ, &n1, &n3); gins(AMOVQ, &n1, &n3);
regfree(&n1); regfree(&n1);
regfree(&n2);
reg[D_AX] = 0; reg[D_AX] = 0;
cgen_div(op, nl, nr, res); cgen_div(op, nl, nr, res);
...@@ -868,12 +875,12 @@ cgen_div(int op, Node *nl, Node *nr, Node *res) ...@@ -868,12 +875,12 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
return; return;
} }
regalloc(&n2, nr->type, &n2); // clean out the DX register
if(rdx && !samereg(res, &n2)) { if(rdx && !samereg(res, &n2)) {
// clean out the DX register
regalloc(&n3, types[TINT64], N); regalloc(&n3, types[TINT64], N);
gins(AMOVQ, &n2, &n3); gins(AMOVQ, &n2, &n3);
regfree(&n1); regfree(&n1);
regfree(&n2);
reg[D_DX] = 0; reg[D_DX] = 0;
cgen_div(op, nl, nr, res); cgen_div(op, nl, nr, res);
...@@ -891,18 +898,18 @@ cgen_div(int op, Node *nl, Node *nr, Node *res) ...@@ -891,18 +898,18 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
gmove(&n3, &n2); gmove(&n3, &n2);
} }
regalloc(&n3, nr->type, res); regalloc(&n3, nr->type, N);
if(nl->ullman >= nr->ullman) { if(nl->ullman >= nr->ullman) {
cgen(nl, &n1); cgen(nl, &n1);
if(issigned[nl->type->etype]) if(issigned[nl->type->etype])
gins(ACDQ, N, N); gins(optoas(OFOR, nl->type), N, N);
cgen(nr, &n3); cgen(nr, &n3);
gins(a, &n3, N); gins(a, &n3, N);
} else { } else {
cgen(nr, &n3); cgen(nr, &n3);
cgen(nl, &n1); cgen(nl, &n1);
if(issigned[nl->type->etype]) if(issigned[nl->type->etype])
gins(ACDQ, N, N); gins(optoas(OFOR, nl->type), N, N);
gins(a, &n3, N); gins(a, &n3, N);
} }
regfree(&n3); regfree(&n3);
...@@ -915,3 +922,60 @@ cgen_div(int op, Node *nl, Node *nr, Node *res) ...@@ -915,3 +922,60 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
regfree(&n1); regfree(&n1);
regfree(&n2); regfree(&n2);
} }
/*
* this is hard because shift
* count is either constant
* or the CL register
*/
void
cgen_shift(int op, Node *nl, Node *nr, Node *res)
{
Node n1, n2;
int a, rcl;
a = optoas(op, nl->type);
if(nr->op == OLITERAL) {
regalloc(&n1, nr->type, res);
cgen(nl, &n1);
gins(a, nr, &n1);
gmove(&n1, res);
regfree(&n1);
return;
}
rcl = reg[D_CX];
nodreg(&n1, types[TINT64], D_CX);
regalloc(&n1, nr->type, &n1);
// clean out the CL register
if(rcl && !samereg(res, &n1)) {
regalloc(&n2, types[TINT64], N);
gins(AMOVQ, &n1, &n2);
regfree(&n1);
reg[D_CX] = 0;
cgen_shift(op, nl, nr, res);
reg[D_CX] = rcl;
gins(AMOVQ, &n2, &n1);
regfree(&n2);
return;
}
regalloc(&n2, nl->type, res); // can one shift the CL register?
if(nl->ullman >= nr->ullman) {
cgen(nl, &n2);
cgen(nr, &n1);
} else {
cgen(nr, &n1);
cgen(nl, &n2);
}
gins(a, &n1, &n2);
gmove(&n2, res);
regfree(&n1);
regfree(&n2);
}
...@@ -118,6 +118,7 @@ void cgen_callmeth(Node*); ...@@ -118,6 +118,7 @@ void cgen_callmeth(Node*);
void cgen_callinter(Node*, Node*); void cgen_callinter(Node*, Node*);
void cgen_callret(Node*, Node*); void cgen_callret(Node*, Node*);
void cgen_div(int, Node*, Node*, Node*); void cgen_div(int, Node*, Node*, Node*);
void cgen_shift(int, Node*, Node*, Node*);
void genpanic(void); void genpanic(void);
int needconvert(Type*, Type*); int needconvert(Type*, Type*);
void genconv(Type*, Type*); void genconv(Type*, Type*);
......
...@@ -1354,38 +1354,82 @@ optoas(int op, Type *t) ...@@ -1354,38 +1354,82 @@ optoas(int op, Type *t)
a = ANEGQ; a = ANEGQ;
break; break;
case CASE(OMUL, TINT8): case CASE(OLSH, TINT8):
a = AIMULB; case CASE(OLSH, TUINT8):
a = ASHLB;
break; break;
case CASE(OMUL, TUINT8): case CASE(OLSH, TINT16):
a = AMULB; case CASE(OLSH, TUINT16):
a = ASHLW;
break; break;
case CASE(OMUL, TINT16): case CASE(OLSH, TINT32):
a = AIMULW; case CASE(OLSH, TUINT32):
case CASE(OLSH, TPTR32):
a = ASHLL;
break; break;
case CASE(OMUL, TUINT16): case CASE(OLSH, TINT64):
a = AMULW; case CASE(OLSH, TUINT64):
case CASE(OLSH, TPTR64):
a = ASHLQ;
break; break;
case CASE(OMUL, TINT32): case CASE(ORSH, TUINT8):
a = AIMULL; a = ASHRB;
break;
case CASE(ORSH, TUINT16):
a = ASHRW;
break;
case CASE(ORSH, TUINT32):
case CASE(ORSH, TPTR32):
a = ASHRL;
break;
case CASE(ORSH, TUINT64):
case CASE(ORSH, TPTR64):
a = ASHRQ;
break;
case CASE(ORSH, TINT8):
a = ASARB;
break;
case CASE(ORSH, TINT16):
a = ASARW;
break;
case CASE(ORSH, TINT32):
a = ASARL;
break;
case CASE(ORSH, TINT64):
a = ASARQ;
break; break;
case CASE(OMUL, TINT8):
case CASE(OMUL, TUINT8):
a = AIMULB;
break;
case CASE(OMUL, TINT16):
case CASE(OMUL, TUINT16):
a = AIMULW;
break;
case CASE(OMUL, TINT32):
case CASE(OMUL, TUINT32): case CASE(OMUL, TUINT32):
case CASE(OMUL, TPTR32): case CASE(OMUL, TPTR32):
a = AMULL; a = AIMULL;
break; break;
case CASE(OMUL, TINT64): case CASE(OMUL, TINT64):
a = AIMULQ;
break;
case CASE(OMUL, TUINT64): case CASE(OMUL, TUINT64):
case CASE(OMUL, TPTR64): case CASE(OMUL, TPTR64):
a = AMULQ; a = AIMULQ;
break; break;
case CASE(OMUL, TFLOAT32): case CASE(OMUL, TFLOAT32):
...@@ -1440,6 +1484,18 @@ optoas(int op, Type *t) ...@@ -1440,6 +1484,18 @@ optoas(int op, Type *t)
a = ADIVQ; a = ADIVQ;
break; break;
case CASE(OFOR, TINT16):
a = ACWD;
break;
case CASE(OFOR, TINT32):
a = ACDQ;
break;
case CASE(OFOR, TINT64):
a = ACQO;
break;
case CASE(ODIV, TFLOAT32): case CASE(ODIV, TFLOAT32):
a = ADIVSS; a = ADIVSS;
break; break;
......
...@@ -16,4 +16,4 @@ $a ...@@ -16,4 +16,4 @@ $a
. .
w sysimport.c w sysimport.c
q' | ed foop.6 q' | ed sys.6
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment