diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-07-30 19:11:16 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-07-30 19:11:16 +0200 |
commit | 4f33c88a51587681b7be1ae57cfbc43b627c6bc4 (patch) | |
tree | 25560404dc80007e5dc268811242c9071f6a1017 /sys/src/cmd/6c/sgen.c | |
parent | fcc5e75d07e5bc6cb3ddac6d9a437e7ec62d0d95 (diff) |
import updated compilers from sources
Diffstat (limited to 'sys/src/cmd/6c/sgen.c')
-rw-r--r-- | sys/src/cmd/6c/sgen.c | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/sys/src/cmd/6c/sgen.c b/sys/src/cmd/6c/sgen.c new file mode 100644 index 000000000..a7d751c0f --- /dev/null +++ b/sys/src/cmd/6c/sgen.c @@ -0,0 +1,435 @@ +#include "gc.h" + +void +noretval(int n) +{ + + if(n & 1) { + gins(ANOP, Z, Z); + p->to.type = REGRET; + } + if(n & 2) { + gins(ANOP, Z, Z); + p->to.type = FREGRET; + } +} + +/* welcome to commute */ +static void +commute(Node *n) +{ + Node *l, *r; + + l = n->left; + r = n->right; + if(r->complex > l->complex) { + n->left = r; + n->right = l; + } +} + +void +indexshift(Node *n) +{ + int g; + + if(!typechlpv[n->type->etype]) + return; + simplifyshift(n); + if(n->op == OASHL && n->right->op == OCONST){ + g = vconst(n->right); + if(g >= 0 && g <= 3) + n->addable = 7; + } +} + +/* + * calculate addressability as follows + * NAME ==> 10/11 name+value(SB/SP) + * REGISTER ==> 12 register + * CONST ==> 20 $value + * *(20) ==> 21 value + * &(10) ==> 13 $name+value(SB) + * &(11) ==> 1 $name+value(SP) + * (13) + (20) ==> 13 fold constants + * (1) + (20) ==> 1 fold constants + * *(13) ==> 10 back to name + * *(1) ==> 11 back to name + * + * (20) * (X) ==> 7 multiplier in indexing + * (X,7) + (13,1) ==> 8 adder in indexing (addresses) + * (8) ==> &9(OINDEX) index, almost addressable + * + * calculate complexity (number of registers) + */ +void +xcom(Node *n) +{ + Node *l, *r; + int g; + + if(n == Z) + return; + l = n->left; + r = n->right; + n->complex = 0; + n->addable = 0; + switch(n->op) { + case OCONST: + n->addable = 20; + break; + + case ONAME: + n->addable = 10; + if(n->class == CPARAM || n->class == CAUTO) + n->addable = 11; + break; + + case OREGISTER: + n->addable = 12; + break; + + case OINDREG: + n->addable = 12; + break; + + case OADDR: + xcom(l); + if(l->addable == 10) + n->addable = 13; + else + if(l->addable == 11) + n->addable = 1; + break; + + case OADD: + xcom(l); + xcom(r); + if(n->type->etype != TIND) + break; + + switch(r->addable) { + case 20: + switch(l->addable) { + case 1: + case 13: + commadd: + l->type = n->type; + *n = *l; + l = new(0, Z, Z); + *l = *(n->left); + l->xoffset += r->vconst; + n->left = l; + r = n->right; + goto brk; + } + break; + + case 1: + case 13: + case 10: + case 11: + /* l is the base, r is the index */ + if(l->addable != 20) + n->addable = 8; + break; + } + switch(l->addable) { + case 20: + switch(r->addable) { + case 13: + case 1: + r = n->left; + l = n->right; + n->left = l; + n->right = r; + goto commadd; + } + break; + + case 13: + case 1: + case 10: + case 11: + /* r is the base, l is the index */ + if(r->addable != 20) + n->addable = 8; + break; + } + if(n->addable == 8 && !side(n)) { + indx(n); + l = new1(OINDEX, idx.basetree, idx.regtree); + l->scale = idx.scale; + l->addable = 9; + l->complex = l->right->complex; + l->type = l->left->type; + n->op = OADDR; + n->left = l; + n->right = Z; + n->addable = 8; + break; + } + break; + + case OINDEX: + xcom(l); + xcom(r); + n->addable = 9; + break; + + case OIND: + xcom(l); + if(l->op == OADDR) { + l = l->left; + l->type = n->type; + *n = *l; + return; + } + switch(l->addable) { + case 20: + n->addable = 21; + break; + case 1: + n->addable = 11; + break; + case 13: + n->addable = 10; + break; + } + break; + + case OASHL: + xcom(l); + xcom(r); + indexshift(n); + break; + + case OMUL: + case OLMUL: + xcom(l); + xcom(r); + g = vlog(l); + if(g >= 0) { + n->left = r; + n->right = l; + l = r; + r = n->right; + } + g = vlog(r); + if(g >= 0) { + n->op = OASHL; + r->vconst = g; + r->type = types[TINT]; + indexshift(n); + break; + } + commute(n); + break; + + case OASLDIV: + xcom(l); + xcom(r); + g = vlog(r); + if(g >= 0) { + n->op = OASLSHR; + r->vconst = g; + r->type = types[TINT]; + } + break; + + case OLDIV: + xcom(l); + xcom(r); + g = vlog(r); + if(g >= 0) { + n->op = OLSHR; + r->vconst = g; + r->type = types[TINT]; + indexshift(n); + break; + } + break; + + case OASLMOD: + xcom(l); + xcom(r); + g = vlog(r); + if(g >= 0) { + n->op = OASAND; + r->vconst--; + } + break; + + case OLMOD: + xcom(l); + xcom(r); + g = vlog(r); + if(g >= 0) { + n->op = OAND; + r->vconst--; + } + break; + + case OASMUL: + case OASLMUL: + xcom(l); + xcom(r); + g = vlog(r); + if(g >= 0) { + n->op = OASASHL; + r->vconst = g; + } + break; + + case OLSHR: + case OASHR: + xcom(l); + xcom(r); + indexshift(n); + break; + + default: + if(l != Z) + xcom(l); + if(r != Z) + xcom(r); + break; + } +brk: + if(n->addable >= 10) + return; + if(l != Z) + n->complex = l->complex; + if(r != Z) { + if(r->complex == n->complex) + n->complex = r->complex+1; + else + if(r->complex > n->complex) + n->complex = r->complex; + } + if(n->complex == 0) + n->complex++; + + switch(n->op) { + + case OFUNC: + n->complex = FNX; + break; + + case OCAST: + if(l->type->etype == TUVLONG && typefd[n->type->etype]) + n->complex += 2; + break; + + case OLMOD: + case OMOD: + case OLMUL: + case OLDIV: + case OMUL: + case ODIV: + case OASLMUL: + case OASLDIV: + case OASLMOD: + case OASMUL: + case OASDIV: + case OASMOD: + if(r->complex >= l->complex) { + n->complex = l->complex + 3; + if(r->complex > n->complex) + n->complex = r->complex; + } else { + n->complex = r->complex + 3; + if(l->complex > n->complex) + n->complex = l->complex; + } + break; + + case OLSHR: + case OASHL: + case OASHR: + case OASLSHR: + case OASASHL: + case OASASHR: + if(r->complex >= l->complex) { + n->complex = l->complex + 2; + if(r->complex > n->complex) + n->complex = r->complex; + } else { + n->complex = r->complex + 2; + if(l->complex > n->complex) + n->complex = l->complex; + } + break; + + case OADD: + case OXOR: + case OAND: + case OOR: + /* + * immediate operators, make const on right + */ + if(l->op == OCONST) { + n->left = r; + n->right = l; + } + break; + + case OEQ: + case ONE: + case OLE: + case OLT: + case OGE: + case OGT: + case OHI: + case OHS: + case OLO: + case OLS: + /* + * compare operators, make const on left + */ + if(r->op == OCONST) { + n->left = r; + n->right = l; + n->op = invrel[relindex(n->op)]; + } + break; + } +} + +void +indx(Node *n) +{ + Node *l, *r; + + if(debug['x']) + prtree(n, "indx"); + + l = n->left; + r = n->right; + if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) { + n->right = l; + n->left = r; + l = r; + r = n->right; + } + if(l->addable != 7) { + idx.regtree = l; + idx.scale = 1; + } else + if(l->right->addable == 20) { + idx.regtree = l->left; + idx.scale = 1 << l->right->vconst; + } else + if(l->left->addable == 20) { + idx.regtree = l->right; + idx.scale = 1 << l->left->vconst; + } else + diag(n, "bad index"); + + idx.basetree = r; + if(debug['x']) { + print("scale = %d\n", idx.scale); + prtree(idx.regtree, "index"); + prtree(idx.basetree, "base"); + } +} |