17edc7532SDavid du Colombier #include "gc.h"
27edc7532SDavid du Colombier
3*cd2352d6SDavid du Colombier static void genasop(int, Node*, Node*, Node*);
4*cd2352d6SDavid du Colombier
57edc7532SDavid du Colombier void
cgen(Node * n,Node * nn)67edc7532SDavid du Colombier cgen(Node *n, Node *nn)
77edc7532SDavid du Colombier {
87edc7532SDavid du Colombier Node *l, *r;
97edc7532SDavid du Colombier Prog *p1;
107edc7532SDavid du Colombier Node nod, nod1, nod2, nod3, nod4;
117edc7532SDavid du Colombier int o;
127edc7532SDavid du Colombier long v, curs;
137edc7532SDavid du Colombier
147edc7532SDavid du Colombier if(debug['g']) {
157edc7532SDavid du Colombier prtree(nn, "cgen lhs");
167edc7532SDavid du Colombier prtree(n, "cgen");
177edc7532SDavid du Colombier }
187edc7532SDavid du Colombier if(n == Z || n->type == T)
197edc7532SDavid du Colombier return;
207edc7532SDavid du Colombier if(typesu[n->type->etype]) {
217edc7532SDavid du Colombier sugen(n, nn, n->type->width);
227edc7532SDavid du Colombier return;
237edc7532SDavid du Colombier }
247edc7532SDavid du Colombier l = n->left;
257edc7532SDavid du Colombier r = n->right;
267edc7532SDavid du Colombier o = n->op;
277edc7532SDavid du Colombier if(n->addable >= INDEXED) {
287edc7532SDavid du Colombier if(nn == Z) {
297edc7532SDavid du Colombier switch(o) {
307edc7532SDavid du Colombier default:
317edc7532SDavid du Colombier nullwarn(Z, Z);
327edc7532SDavid du Colombier break;
337edc7532SDavid du Colombier case OINDEX:
347edc7532SDavid du Colombier nullwarn(l, r);
357edc7532SDavid du Colombier break;
367edc7532SDavid du Colombier }
377edc7532SDavid du Colombier return;
387edc7532SDavid du Colombier }
397edc7532SDavid du Colombier gmove(n, nn);
407edc7532SDavid du Colombier return;
417edc7532SDavid du Colombier }
427edc7532SDavid du Colombier curs = cursafe;
437edc7532SDavid du Colombier
447edc7532SDavid du Colombier if(n->complex >= FNX)
457edc7532SDavid du Colombier if(l->complex >= FNX)
467edc7532SDavid du Colombier if(r != Z && r->complex >= FNX)
477edc7532SDavid du Colombier switch(o) {
487edc7532SDavid du Colombier default:
497edc7532SDavid du Colombier regret(&nod, r);
507edc7532SDavid du Colombier cgen(r, &nod);
517edc7532SDavid du Colombier
527edc7532SDavid du Colombier regsalloc(&nod1, r);
537edc7532SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
547edc7532SDavid du Colombier
557edc7532SDavid du Colombier regfree(&nod);
567edc7532SDavid du Colombier nod = *n;
577edc7532SDavid du Colombier nod.right = &nod1;
587edc7532SDavid du Colombier cgen(&nod, nn);
597edc7532SDavid du Colombier return;
607edc7532SDavid du Colombier
617edc7532SDavid du Colombier case OFUNC:
627edc7532SDavid du Colombier case OCOMMA:
637edc7532SDavid du Colombier case OANDAND:
647edc7532SDavid du Colombier case OOROR:
657edc7532SDavid du Colombier case OCOND:
667edc7532SDavid du Colombier case ODOT:
677edc7532SDavid du Colombier break;
687edc7532SDavid du Colombier }
697edc7532SDavid du Colombier
707edc7532SDavid du Colombier switch(o) {
717edc7532SDavid du Colombier default:
727edc7532SDavid du Colombier diag(n, "unknown op in cgen: %O", o);
737edc7532SDavid du Colombier break;
747edc7532SDavid du Colombier
757edc7532SDavid du Colombier case OAS:
767edc7532SDavid du Colombier if(l->op == OBIT)
777edc7532SDavid du Colombier goto bitas;
787edc7532SDavid du Colombier if(l->addable >= INDEXED && l->complex < FNX) {
797edc7532SDavid du Colombier if(nn != Z || r->addable < INDEXED) {
807edc7532SDavid du Colombier if(r->complex >= FNX && nn == Z)
817edc7532SDavid du Colombier regret(&nod, r);
827edc7532SDavid du Colombier else
837edc7532SDavid du Colombier regalloc(&nod, r, nn);
847edc7532SDavid du Colombier cgen(r, &nod);
857edc7532SDavid du Colombier gmove(&nod, l);
867edc7532SDavid du Colombier if(nn != Z)
877edc7532SDavid du Colombier gmove(&nod, nn);
887edc7532SDavid du Colombier regfree(&nod);
897edc7532SDavid du Colombier } else
907edc7532SDavid du Colombier gmove(r, l);
917edc7532SDavid du Colombier break;
927edc7532SDavid du Colombier }
937edc7532SDavid du Colombier if(l->complex >= r->complex) {
947edc7532SDavid du Colombier reglcgen(&nod1, l, Z);
957edc7532SDavid du Colombier if(r->addable >= INDEXED) {
967edc7532SDavid du Colombier gmove(r, &nod1);
977edc7532SDavid du Colombier if(nn != Z)
987edc7532SDavid du Colombier gmove(r, nn);
997edc7532SDavid du Colombier regfree(&nod1);
1007edc7532SDavid du Colombier break;
1017edc7532SDavid du Colombier }
1027edc7532SDavid du Colombier regalloc(&nod, r, nn);
1037edc7532SDavid du Colombier cgen(r, &nod);
1047edc7532SDavid du Colombier } else {
1057edc7532SDavid du Colombier regalloc(&nod, r, nn);
1067edc7532SDavid du Colombier cgen(r, &nod);
1077edc7532SDavid du Colombier reglcgen(&nod1, l, Z);
1087edc7532SDavid du Colombier }
1097edc7532SDavid du Colombier gmove(&nod, &nod1);
1107edc7532SDavid du Colombier regfree(&nod);
1117edc7532SDavid du Colombier regfree(&nod1);
1127edc7532SDavid du Colombier break;
1137edc7532SDavid du Colombier
1147edc7532SDavid du Colombier bitas:
1157edc7532SDavid du Colombier n = l->left;
1167edc7532SDavid du Colombier regalloc(&nod, r, nn);
1177edc7532SDavid du Colombier if(l->complex >= r->complex) {
1187edc7532SDavid du Colombier reglcgen(&nod1, n, Z);
1197edc7532SDavid du Colombier cgen(r, &nod);
1207edc7532SDavid du Colombier } else {
1217edc7532SDavid du Colombier cgen(r, &nod);
1227edc7532SDavid du Colombier reglcgen(&nod1, n, Z);
1237edc7532SDavid du Colombier }
1247edc7532SDavid du Colombier regalloc(&nod2, n, Z);
1257edc7532SDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
1267edc7532SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
1277edc7532SDavid du Colombier break;
1287edc7532SDavid du Colombier
1297edc7532SDavid du Colombier case OBIT:
1307edc7532SDavid du Colombier if(nn == Z) {
1317edc7532SDavid du Colombier nullwarn(l, Z);
1327edc7532SDavid du Colombier break;
1337edc7532SDavid du Colombier }
1347edc7532SDavid du Colombier bitload(n, &nod, Z, Z, nn);
1357edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
1367edc7532SDavid du Colombier regfree(&nod);
1377edc7532SDavid du Colombier break;
1387edc7532SDavid du Colombier
1397edc7532SDavid du Colombier case OADD:
1407edc7532SDavid du Colombier case OSUB:
1417edc7532SDavid du Colombier case OAND:
1427edc7532SDavid du Colombier case OOR:
1437edc7532SDavid du Colombier case OXOR:
1447edc7532SDavid du Colombier case OLSHR:
1457edc7532SDavid du Colombier case OASHL:
1467edc7532SDavid du Colombier case OASHR:
1477edc7532SDavid du Colombier /*
1487edc7532SDavid du Colombier * immediate operands
1497edc7532SDavid du Colombier */
1507edc7532SDavid du Colombier if(nn != Z)
1517edc7532SDavid du Colombier if(r->op == OCONST)
1527edc7532SDavid du Colombier if(!typefd[n->type->etype]) {
1537edc7532SDavid du Colombier cgen(l, nn);
1547edc7532SDavid du Colombier if(r->vconst == 0)
1557edc7532SDavid du Colombier if(o != OAND)
1567edc7532SDavid du Colombier break;
1577edc7532SDavid du Colombier if(nn != Z)
1587edc7532SDavid du Colombier gopcode(o, r, Z, nn);
1597edc7532SDavid du Colombier break;
1607edc7532SDavid du Colombier }
1617edc7532SDavid du Colombier
1627edc7532SDavid du Colombier case OLMUL:
1637edc7532SDavid du Colombier case OLDIV:
1647edc7532SDavid du Colombier case OLMOD:
1657edc7532SDavid du Colombier case OMUL:
1667edc7532SDavid du Colombier case ODIV:
1677edc7532SDavid du Colombier case OMOD:
1687edc7532SDavid du Colombier if(nn == Z) {
1697edc7532SDavid du Colombier nullwarn(l, r);
1707edc7532SDavid du Colombier break;
1717edc7532SDavid du Colombier }
1727edc7532SDavid du Colombier if(o == OMUL || o == OLMUL) {
1737edc7532SDavid du Colombier if(mulcon(n, nn))
1747edc7532SDavid du Colombier break;
1757edc7532SDavid du Colombier }
1767edc7532SDavid du Colombier if(l->complex >= r->complex) {
1777edc7532SDavid du Colombier regalloc(&nod, l, nn);
1787edc7532SDavid du Colombier cgen(l, &nod);
1797edc7532SDavid du Colombier regalloc(&nod1, r, Z);
1807edc7532SDavid du Colombier cgen(r, &nod1);
1817edc7532SDavid du Colombier gopcode(o, &nod1, Z, &nod);
1827edc7532SDavid du Colombier } else {
1837edc7532SDavid du Colombier regalloc(&nod, r, nn);
1847edc7532SDavid du Colombier cgen(r, &nod);
1857edc7532SDavid du Colombier regalloc(&nod1, l, Z);
1867edc7532SDavid du Colombier cgen(l, &nod1);
1877edc7532SDavid du Colombier gopcode(o, &nod, &nod1, &nod);
1887edc7532SDavid du Colombier }
1897edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
1907edc7532SDavid du Colombier regfree(&nod);
1917edc7532SDavid du Colombier regfree(&nod1);
1927edc7532SDavid du Colombier break;
1937edc7532SDavid du Colombier
1947edc7532SDavid du Colombier case OASLSHR:
1957edc7532SDavid du Colombier case OASASHL:
1967edc7532SDavid du Colombier case OASASHR:
1977edc7532SDavid du Colombier case OASAND:
1987edc7532SDavid du Colombier case OASADD:
1997edc7532SDavid du Colombier case OASSUB:
2007edc7532SDavid du Colombier case OASXOR:
2017edc7532SDavid du Colombier case OASOR:
2027edc7532SDavid du Colombier if(l->op == OBIT)
2037edc7532SDavid du Colombier goto asbitop;
2047edc7532SDavid du Colombier if(r->op == OCONST)
205f8bc6aafSDavid du Colombier if(!typefd[r->type->etype])
2067edc7532SDavid du Colombier if(!typefd[n->type->etype]) {
2077edc7532SDavid du Colombier if(l->addable < INDEXED)
2087edc7532SDavid du Colombier reglcgen(&nod2, l, Z);
2097edc7532SDavid du Colombier else
2107edc7532SDavid du Colombier nod2 = *l;
211f8bc6aafSDavid du Colombier regalloc(&nod, r, nn);
2127edc7532SDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
2137edc7532SDavid du Colombier gopcode(o, r, Z, &nod);
2147edc7532SDavid du Colombier gopcode(OAS, &nod, Z, &nod2);
2157edc7532SDavid du Colombier
2167edc7532SDavid du Colombier regfree(&nod);
2177edc7532SDavid du Colombier if(l->addable < INDEXED)
2187edc7532SDavid du Colombier regfree(&nod2);
2197edc7532SDavid du Colombier break;
2207edc7532SDavid du Colombier }
221*cd2352d6SDavid du Colombier genasop(o, l, r, nn);
222*cd2352d6SDavid du Colombier break;
2237edc7532SDavid du Colombier
2247edc7532SDavid du Colombier case OASLMUL:
2257edc7532SDavid du Colombier case OASLDIV:
2267edc7532SDavid du Colombier case OASLMOD:
2277edc7532SDavid du Colombier case OASMUL:
2287edc7532SDavid du Colombier case OASDIV:
2297edc7532SDavid du Colombier case OASMOD:
2307edc7532SDavid du Colombier if(l->op == OBIT)
2317edc7532SDavid du Colombier goto asbitop;
232*cd2352d6SDavid du Colombier genasop(o, l, r, nn);
2337edc7532SDavid du Colombier break;
2347edc7532SDavid du Colombier
2357edc7532SDavid du Colombier asbitop:
2367edc7532SDavid du Colombier regalloc(&nod4, n, nn);
2377edc7532SDavid du Colombier if(l->complex >= r->complex) {
2387edc7532SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
2397edc7532SDavid du Colombier regalloc(&nod3, r, Z);
2407edc7532SDavid du Colombier cgen(r, &nod3);
2417edc7532SDavid du Colombier } else {
2427edc7532SDavid du Colombier regalloc(&nod3, r, Z);
2437edc7532SDavid du Colombier cgen(r, &nod3);
2447edc7532SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
2457edc7532SDavid du Colombier }
2467edc7532SDavid du Colombier gmove(&nod, &nod4);
2477edc7532SDavid du Colombier gopcode(o, &nod3, Z, &nod4);
2487edc7532SDavid du Colombier regfree(&nod3);
2497edc7532SDavid du Colombier gmove(&nod4, &nod);
2507edc7532SDavid du Colombier regfree(&nod4);
2517edc7532SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
2527edc7532SDavid du Colombier break;
2537edc7532SDavid du Colombier
2547edc7532SDavid du Colombier case OADDR:
2557edc7532SDavid du Colombier if(nn == Z) {
2567edc7532SDavid du Colombier nullwarn(l, Z);
2577edc7532SDavid du Colombier break;
2587edc7532SDavid du Colombier }
2597edc7532SDavid du Colombier lcgen(l, nn);
2607edc7532SDavid du Colombier break;
2617edc7532SDavid du Colombier
2627edc7532SDavid du Colombier case OFUNC:
2637edc7532SDavid du Colombier if(l->complex >= FNX) {
2647edc7532SDavid du Colombier if(l->op != OIND)
2657edc7532SDavid du Colombier diag(n, "bad function call");
2667edc7532SDavid du Colombier
2677edc7532SDavid du Colombier regret(&nod, l->left);
2687edc7532SDavid du Colombier cgen(l->left, &nod);
2697edc7532SDavid du Colombier regsalloc(&nod1, l->left);
2707edc7532SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
2717edc7532SDavid du Colombier regfree(&nod);
2727edc7532SDavid du Colombier
2737edc7532SDavid du Colombier nod = *n;
2747edc7532SDavid du Colombier nod.left = &nod2;
2757edc7532SDavid du Colombier nod2 = *l;
2767edc7532SDavid du Colombier nod2.left = &nod1;
2777edc7532SDavid du Colombier nod2.complex = 1;
2787edc7532SDavid du Colombier cgen(&nod, nn);
2797edc7532SDavid du Colombier
2807edc7532SDavid du Colombier return;
2817edc7532SDavid du Colombier }
2827edc7532SDavid du Colombier o = reg[REGARG];
2837edc7532SDavid du Colombier gargs(r, &nod, &nod1);
2847edc7532SDavid du Colombier if(l->addable < INDEXED) {
2857edc7532SDavid du Colombier reglcgen(&nod, l, Z);
2867edc7532SDavid du Colombier gopcode(OFUNC, Z, Z, &nod);
2877edc7532SDavid du Colombier regfree(&nod);
2887edc7532SDavid du Colombier } else
2897edc7532SDavid du Colombier gopcode(OFUNC, Z, Z, l);
2907edc7532SDavid du Colombier if(REGARG)
2917edc7532SDavid du Colombier if(o != reg[REGARG])
2927edc7532SDavid du Colombier reg[REGARG]--;
2937edc7532SDavid du Colombier if(nn != Z) {
2947edc7532SDavid du Colombier regret(&nod, n);
2957edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
2967edc7532SDavid du Colombier regfree(&nod);
2977edc7532SDavid du Colombier }
2987edc7532SDavid du Colombier break;
2997edc7532SDavid du Colombier
3007edc7532SDavid du Colombier case OIND:
3017edc7532SDavid du Colombier if(nn == Z) {
3027edc7532SDavid du Colombier nullwarn(l, Z);
3037edc7532SDavid du Colombier break;
3047edc7532SDavid du Colombier }
3057edc7532SDavid du Colombier regialloc(&nod, n, nn);
3067edc7532SDavid du Colombier r = l;
3077edc7532SDavid du Colombier while(r->op == OADD)
3087edc7532SDavid du Colombier r = r->right;
3097edc7532SDavid du Colombier if(sconst(r)) {
3107edc7532SDavid du Colombier v = r->vconst;
3117edc7532SDavid du Colombier r->vconst = 0;
3127edc7532SDavid du Colombier cgen(l, &nod);
3137edc7532SDavid du Colombier nod.xoffset += v;
3147edc7532SDavid du Colombier r->vconst = v;
3157edc7532SDavid du Colombier } else
3167edc7532SDavid du Colombier cgen(l, &nod);
3177edc7532SDavid du Colombier regind(&nod, n);
3187edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
3197edc7532SDavid du Colombier regfree(&nod);
3207edc7532SDavid du Colombier break;
3217edc7532SDavid du Colombier
3227edc7532SDavid du Colombier case OEQ:
3237edc7532SDavid du Colombier case ONE:
3247edc7532SDavid du Colombier case OLE:
3257edc7532SDavid du Colombier case OLT:
3267edc7532SDavid du Colombier case OGE:
3277edc7532SDavid du Colombier case OGT:
3287edc7532SDavid du Colombier case OLO:
3297edc7532SDavid du Colombier case OLS:
3307edc7532SDavid du Colombier case OHI:
3317edc7532SDavid du Colombier case OHS:
3327edc7532SDavid du Colombier if(nn == Z) {
3337edc7532SDavid du Colombier nullwarn(l, r);
3347edc7532SDavid du Colombier break;
3357edc7532SDavid du Colombier }
3367edc7532SDavid du Colombier boolgen(n, 1, nn);
3377edc7532SDavid du Colombier break;
3387edc7532SDavid du Colombier
3397edc7532SDavid du Colombier case OANDAND:
3407edc7532SDavid du Colombier case OOROR:
3417edc7532SDavid du Colombier boolgen(n, 1, nn);
3427edc7532SDavid du Colombier if(nn == Z)
3437edc7532SDavid du Colombier patch(p, pc);
3447edc7532SDavid du Colombier break;
3457edc7532SDavid du Colombier
3467edc7532SDavid du Colombier case ONOT:
3477edc7532SDavid du Colombier if(nn == Z) {
3487edc7532SDavid du Colombier nullwarn(l, Z);
3497edc7532SDavid du Colombier break;
3507edc7532SDavid du Colombier }
3517edc7532SDavid du Colombier boolgen(n, 1, nn);
3527edc7532SDavid du Colombier break;
3537edc7532SDavid du Colombier
3547edc7532SDavid du Colombier case OCOMMA:
3557edc7532SDavid du Colombier cgen(l, Z);
3567edc7532SDavid du Colombier cgen(r, nn);
3577edc7532SDavid du Colombier break;
3587edc7532SDavid du Colombier
3597edc7532SDavid du Colombier case OCAST:
3607edc7532SDavid du Colombier if(nn == Z) {
3617edc7532SDavid du Colombier nullwarn(l, Z);
3627edc7532SDavid du Colombier break;
3637edc7532SDavid du Colombier }
3647edc7532SDavid du Colombier /*
3657edc7532SDavid du Colombier * convert from types l->n->nn
3667edc7532SDavid du Colombier */
3677edc7532SDavid du Colombier if(nocast(l->type, n->type)) {
3687edc7532SDavid du Colombier if(nocast(n->type, nn->type)) {
3697edc7532SDavid du Colombier cgen(l, nn);
3707edc7532SDavid du Colombier break;
3717edc7532SDavid du Colombier }
3727edc7532SDavid du Colombier }
3737edc7532SDavid du Colombier regalloc(&nod, l, nn);
3747edc7532SDavid du Colombier cgen(l, &nod);
3757edc7532SDavid du Colombier regalloc(&nod1, n, &nod);
3767edc7532SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
3777edc7532SDavid du Colombier gopcode(OAS, &nod1, Z, nn);
3787edc7532SDavid du Colombier regfree(&nod1);
3797edc7532SDavid du Colombier regfree(&nod);
3807edc7532SDavid du Colombier break;
3817edc7532SDavid du Colombier
3827edc7532SDavid du Colombier case ODOT:
3837edc7532SDavid du Colombier sugen(l, nodrat, l->type->width);
3847edc7532SDavid du Colombier if(nn != Z) {
3857edc7532SDavid du Colombier warn(n, "non-interruptable temporary");
3867edc7532SDavid du Colombier nod = *nodrat;
3877edc7532SDavid du Colombier if(!r || r->op != OCONST) {
3887edc7532SDavid du Colombier diag(n, "DOT and no offset");
3897edc7532SDavid du Colombier break;
3907edc7532SDavid du Colombier }
3917edc7532SDavid du Colombier nod.xoffset += (long)r->vconst;
3927edc7532SDavid du Colombier nod.type = n->type;
3937edc7532SDavid du Colombier cgen(&nod, nn);
3947edc7532SDavid du Colombier }
3957edc7532SDavid du Colombier break;
3967edc7532SDavid du Colombier
3977edc7532SDavid du Colombier case OCOND:
3987edc7532SDavid du Colombier bcgen(l, 1);
3997edc7532SDavid du Colombier p1 = p;
4007edc7532SDavid du Colombier cgen(r->left, nn);
4017edc7532SDavid du Colombier gbranch(OGOTO);
4027edc7532SDavid du Colombier patch(p1, pc);
4037edc7532SDavid du Colombier p1 = p;
4047edc7532SDavid du Colombier cgen(r->right, nn);
4057edc7532SDavid du Colombier patch(p1, pc);
4067edc7532SDavid du Colombier break;
4077edc7532SDavid du Colombier
4087edc7532SDavid du Colombier case OPOSTINC:
4097edc7532SDavid du Colombier case OPOSTDEC:
4107edc7532SDavid du Colombier v = 1;
4117edc7532SDavid du Colombier if(l->type->etype == TIND)
4127edc7532SDavid du Colombier v = l->type->link->width;
4137edc7532SDavid du Colombier if(o == OPOSTDEC)
4147edc7532SDavid du Colombier v = -v;
4157edc7532SDavid du Colombier if(l->op == OBIT)
4167edc7532SDavid du Colombier goto bitinc;
4177edc7532SDavid du Colombier if(nn == Z)
4187edc7532SDavid du Colombier goto pre;
4197edc7532SDavid du Colombier
4207edc7532SDavid du Colombier if(l->addable < INDEXED)
4217edc7532SDavid du Colombier reglcgen(&nod2, l, Z);
4227edc7532SDavid du Colombier else
4237edc7532SDavid du Colombier nod2 = *l;
4247edc7532SDavid du Colombier
4257edc7532SDavid du Colombier regalloc(&nod, l, nn);
4267edc7532SDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
4277edc7532SDavid du Colombier regalloc(&nod1, l, Z);
4287edc7532SDavid du Colombier if(typefd[l->type->etype]) {
4297edc7532SDavid du Colombier regalloc(&nod3, l, Z);
4307edc7532SDavid du Colombier if(v < 0) {
4317edc7532SDavid du Colombier gopcode(OAS, nodfconst(-v), Z, &nod3);
4327edc7532SDavid du Colombier gopcode(OSUB, &nod3, &nod, &nod1);
4337edc7532SDavid du Colombier } else {
4347edc7532SDavid du Colombier gopcode(OAS, nodfconst(v), Z, &nod3);
4357edc7532SDavid du Colombier gopcode(OADD, &nod3, &nod, &nod1);
4367edc7532SDavid du Colombier }
4377edc7532SDavid du Colombier regfree(&nod3);
4387edc7532SDavid du Colombier } else
4397edc7532SDavid du Colombier gopcode(OADD, nodconst(v), &nod, &nod1);
4407edc7532SDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
4417edc7532SDavid du Colombier
4427edc7532SDavid du Colombier regfree(&nod);
4437edc7532SDavid du Colombier regfree(&nod1);
4447edc7532SDavid du Colombier if(l->addable < INDEXED)
4457edc7532SDavid du Colombier regfree(&nod2);
4467edc7532SDavid du Colombier break;
4477edc7532SDavid du Colombier
4487edc7532SDavid du Colombier case OPREINC:
4497edc7532SDavid du Colombier case OPREDEC:
4507edc7532SDavid du Colombier v = 1;
4517edc7532SDavid du Colombier if(l->type->etype == TIND)
4527edc7532SDavid du Colombier v = l->type->link->width;
4537edc7532SDavid du Colombier if(o == OPREDEC)
4547edc7532SDavid du Colombier v = -v;
4557edc7532SDavid du Colombier if(l->op == OBIT)
4567edc7532SDavid du Colombier goto bitinc;
4577edc7532SDavid du Colombier
4587edc7532SDavid du Colombier pre:
4597edc7532SDavid du Colombier if(l->addable < INDEXED)
4607edc7532SDavid du Colombier reglcgen(&nod2, l, Z);
4617edc7532SDavid du Colombier else
4627edc7532SDavid du Colombier nod2 = *l;
4637edc7532SDavid du Colombier
4647edc7532SDavid du Colombier regalloc(&nod, l, nn);
4657edc7532SDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
4667edc7532SDavid du Colombier if(typefd[l->type->etype]) {
4677edc7532SDavid du Colombier regalloc(&nod3, l, Z);
4687edc7532SDavid du Colombier if(v < 0) {
4697edc7532SDavid du Colombier gopcode(OAS, nodfconst(-v), Z, &nod3);
4707edc7532SDavid du Colombier gopcode(OSUB, &nod3, Z, &nod);
4717edc7532SDavid du Colombier } else {
4727edc7532SDavid du Colombier gopcode(OAS, nodfconst(v), Z, &nod3);
4737edc7532SDavid du Colombier gopcode(OADD, &nod3, Z, &nod);
4747edc7532SDavid du Colombier }
4757edc7532SDavid du Colombier regfree(&nod3);
4767edc7532SDavid du Colombier } else
4777edc7532SDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
4787edc7532SDavid du Colombier gopcode(OAS, &nod, Z, &nod2);
479f8bc6aafSDavid du Colombier if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
480f8bc6aafSDavid du Colombier gins(ANOP, l, Z);
4817edc7532SDavid du Colombier
4827edc7532SDavid du Colombier regfree(&nod);
4837edc7532SDavid du Colombier if(l->addable < INDEXED)
4847edc7532SDavid du Colombier regfree(&nod2);
4857edc7532SDavid du Colombier break;
4867edc7532SDavid du Colombier
4877edc7532SDavid du Colombier bitinc:
4887edc7532SDavid du Colombier if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
4897edc7532SDavid du Colombier bitload(l, &nod, &nod1, &nod2, Z);
4907edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
4917edc7532SDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
4927edc7532SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, Z);
4937edc7532SDavid du Colombier break;
4947edc7532SDavid du Colombier }
4957edc7532SDavid du Colombier bitload(l, &nod, &nod1, &nod2, nn);
4967edc7532SDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
4977edc7532SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
4987edc7532SDavid du Colombier break;
4997edc7532SDavid du Colombier }
5007edc7532SDavid du Colombier cursafe = curs;
5017edc7532SDavid du Colombier }
5027edc7532SDavid du Colombier
503*cd2352d6SDavid du Colombier static void
genasop(int o,Node * l,Node * r,Node * nn)504*cd2352d6SDavid du Colombier genasop(int o, Node *l, Node *r, Node *nn)
505*cd2352d6SDavid du Colombier {
506*cd2352d6SDavid du Colombier Node nod, nod1, nod2;
507*cd2352d6SDavid du Colombier int hardleft;
508*cd2352d6SDavid du Colombier
509*cd2352d6SDavid du Colombier hardleft = l->addable < INDEXED || l->complex >= FNX;
510*cd2352d6SDavid du Colombier if(l->complex >= r->complex) {
511*cd2352d6SDavid du Colombier if(hardleft)
512*cd2352d6SDavid du Colombier reglcgen(&nod2, l, Z);
513*cd2352d6SDavid du Colombier else
514*cd2352d6SDavid du Colombier nod2 = *l;
515*cd2352d6SDavid du Colombier regalloc(&nod1, r, Z);
516*cd2352d6SDavid du Colombier cgen(r, &nod1);
517*cd2352d6SDavid du Colombier } else {
518*cd2352d6SDavid du Colombier regalloc(&nod1, r, Z);
519*cd2352d6SDavid du Colombier cgen(r, &nod1);
520*cd2352d6SDavid du Colombier if(hardleft)
521*cd2352d6SDavid du Colombier reglcgen(&nod2, l, Z);
522*cd2352d6SDavid du Colombier else
523*cd2352d6SDavid du Colombier nod2 = *l;
524*cd2352d6SDavid du Colombier }
525*cd2352d6SDavid du Colombier if(nod1.type == nod2.type || !typefd[nod1.type->etype])
526*cd2352d6SDavid du Colombier regalloc(&nod, &nod2, nn);
527*cd2352d6SDavid du Colombier else
528*cd2352d6SDavid du Colombier regalloc(&nod, &nod1, Z);
529*cd2352d6SDavid du Colombier gmove(&nod2, &nod);
530*cd2352d6SDavid du Colombier gopcode(o, &nod1, Z, &nod);
531*cd2352d6SDavid du Colombier gmove(&nod, &nod2);
532*cd2352d6SDavid du Colombier if(nn != Z)
533*cd2352d6SDavid du Colombier gmove(&nod2, nn);
534*cd2352d6SDavid du Colombier regfree(&nod);
535*cd2352d6SDavid du Colombier regfree(&nod1);
536*cd2352d6SDavid du Colombier if(hardleft)
537*cd2352d6SDavid du Colombier regfree(&nod2);
538*cd2352d6SDavid du Colombier }
539*cd2352d6SDavid du Colombier
5407edc7532SDavid du Colombier void
reglcgen(Node * t,Node * n,Node * nn)5417edc7532SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
5427edc7532SDavid du Colombier {
5437edc7532SDavid du Colombier Node *r;
5447edc7532SDavid du Colombier long v;
5457edc7532SDavid du Colombier
5467edc7532SDavid du Colombier regialloc(t, n, nn);
5477edc7532SDavid du Colombier if(n->op == OIND) {
5487edc7532SDavid du Colombier r = n->left;
5497edc7532SDavid du Colombier while(r->op == OADD)
5507edc7532SDavid du Colombier r = r->right;
5517edc7532SDavid du Colombier if(sconst(r)) {
5527edc7532SDavid du Colombier v = r->vconst;
5537edc7532SDavid du Colombier r->vconst = 0;
5547edc7532SDavid du Colombier lcgen(n, t);
5557edc7532SDavid du Colombier t->xoffset += v;
5567edc7532SDavid du Colombier r->vconst = v;
5577edc7532SDavid du Colombier regind(t, n);
5587edc7532SDavid du Colombier return;
5597edc7532SDavid du Colombier }
5607edc7532SDavid du Colombier }
5617edc7532SDavid du Colombier lcgen(n, t);
5627edc7532SDavid du Colombier regind(t, n);
5637edc7532SDavid du Colombier }
5647edc7532SDavid du Colombier
5657edc7532SDavid du Colombier void
lcgen(Node * n,Node * nn)5667edc7532SDavid du Colombier lcgen(Node *n, Node *nn)
5677edc7532SDavid du Colombier {
5687edc7532SDavid du Colombier Prog *p1;
5697edc7532SDavid du Colombier Node nod;
5707edc7532SDavid du Colombier
5717edc7532SDavid du Colombier if(debug['g']) {
5727edc7532SDavid du Colombier prtree(nn, "lcgen lhs");
5737edc7532SDavid du Colombier prtree(n, "lcgen");
5747edc7532SDavid du Colombier }
5757edc7532SDavid du Colombier if(n == Z || n->type == T)
5767edc7532SDavid du Colombier return;
5777edc7532SDavid du Colombier if(nn == Z) {
5787edc7532SDavid du Colombier nn = &nod;
5797edc7532SDavid du Colombier regalloc(&nod, n, Z);
5807edc7532SDavid du Colombier }
5817edc7532SDavid du Colombier switch(n->op) {
5827edc7532SDavid du Colombier default:
5837edc7532SDavid du Colombier if(n->addable < INDEXED) {
5847edc7532SDavid du Colombier diag(n, "unknown op in lcgen: %O", n->op);
5857edc7532SDavid du Colombier break;
5867edc7532SDavid du Colombier }
5877edc7532SDavid du Colombier nod = *n;
5887edc7532SDavid du Colombier nod.op = OADDR;
5897edc7532SDavid du Colombier nod.left = n;
5907edc7532SDavid du Colombier nod.right = Z;
5917edc7532SDavid du Colombier nod.type = types[TIND];
5927edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
5937edc7532SDavid du Colombier break;
5947edc7532SDavid du Colombier
5957edc7532SDavid du Colombier case OCOMMA:
5967edc7532SDavid du Colombier cgen(n->left, n->left);
5977edc7532SDavid du Colombier lcgen(n->right, nn);
5987edc7532SDavid du Colombier break;
5997edc7532SDavid du Colombier
6007edc7532SDavid du Colombier case OIND:
6017edc7532SDavid du Colombier cgen(n->left, nn);
6027edc7532SDavid du Colombier break;
6037edc7532SDavid du Colombier
6047edc7532SDavid du Colombier case OCOND:
6057edc7532SDavid du Colombier bcgen(n->left, 1);
6067edc7532SDavid du Colombier p1 = p;
6077edc7532SDavid du Colombier lcgen(n->right->left, nn);
6087edc7532SDavid du Colombier gbranch(OGOTO);
6097edc7532SDavid du Colombier patch(p1, pc);
6107edc7532SDavid du Colombier p1 = p;
6117edc7532SDavid du Colombier lcgen(n->right->right, nn);
6127edc7532SDavid du Colombier patch(p1, pc);
6137edc7532SDavid du Colombier break;
6147edc7532SDavid du Colombier }
6157edc7532SDavid du Colombier }
6167edc7532SDavid du Colombier
6177edc7532SDavid du Colombier void
bcgen(Node * n,int true)6187edc7532SDavid du Colombier bcgen(Node *n, int true)
6197edc7532SDavid du Colombier {
6207edc7532SDavid du Colombier
6217edc7532SDavid du Colombier if(n->type == T)
6227edc7532SDavid du Colombier gbranch(OGOTO);
6237edc7532SDavid du Colombier else
6247edc7532SDavid du Colombier boolgen(n, true, Z);
6257edc7532SDavid du Colombier }
6267edc7532SDavid du Colombier
6277edc7532SDavid du Colombier void
boolgen(Node * n,int true,Node * nn)6287edc7532SDavid du Colombier boolgen(Node *n, int true, Node *nn)
6297edc7532SDavid du Colombier {
6307edc7532SDavid du Colombier int o;
6317edc7532SDavid du Colombier Prog *p1, *p2;
6327edc7532SDavid du Colombier Node *l, *r, nod, nod1;
6337edc7532SDavid du Colombier long curs;
6347edc7532SDavid du Colombier
6357edc7532SDavid du Colombier if(debug['g']) {
6367edc7532SDavid du Colombier prtree(nn, "boolgen lhs");
6377edc7532SDavid du Colombier prtree(n, "boolgen");
6387edc7532SDavid du Colombier }
6397edc7532SDavid du Colombier curs = cursafe;
6407edc7532SDavid du Colombier l = n->left;
6417edc7532SDavid du Colombier r = n->right;
6427edc7532SDavid du Colombier switch(n->op) {
6437edc7532SDavid du Colombier
6447edc7532SDavid du Colombier default:
6457edc7532SDavid du Colombier regalloc(&nod, n, nn);
6467edc7532SDavid du Colombier cgen(n, &nod);
6477edc7532SDavid du Colombier if(nn == Z || typefd[n->type->etype]) {
6487edc7532SDavid du Colombier o = ONE;
6497edc7532SDavid du Colombier if(true)
6507edc7532SDavid du Colombier o = comrel[relindex(o)];
6517edc7532SDavid du Colombier if(typefd[n->type->etype]) {
6527edc7532SDavid du Colombier nodreg(&nod1, n, NREG+FREGZERO);
6537edc7532SDavid du Colombier gopcode(o, &nod, &nod1, Z);
6547edc7532SDavid du Colombier } else
6557edc7532SDavid du Colombier gopcode(o, &nod, Z, Z);
6567edc7532SDavid du Colombier regfree(&nod);
6577edc7532SDavid du Colombier goto com;
6587edc7532SDavid du Colombier }
6597edc7532SDavid du Colombier if(true)
6607edc7532SDavid du Colombier gopcode(OCOND, &nod, nodconst(0), &nod);
6617edc7532SDavid du Colombier else
6627edc7532SDavid du Colombier gopcode(OCOND, nodconst(1), &nod, &nod);
6637edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
6647edc7532SDavid du Colombier regfree(&nod);
6657edc7532SDavid du Colombier break;
6667edc7532SDavid du Colombier
6677edc7532SDavid du Colombier case OCONST:
6687edc7532SDavid du Colombier o = vconst(n);
6697edc7532SDavid du Colombier if(!true)
6707edc7532SDavid du Colombier o = !o;
6717edc7532SDavid du Colombier gbranch(OGOTO);
6727edc7532SDavid du Colombier if(o) {
6737edc7532SDavid du Colombier p1 = p;
6747edc7532SDavid du Colombier gbranch(OGOTO);
6757edc7532SDavid du Colombier patch(p1, pc);
6767edc7532SDavid du Colombier }
6777edc7532SDavid du Colombier goto com;
6787edc7532SDavid du Colombier
6797edc7532SDavid du Colombier case OCOMMA:
6807edc7532SDavid du Colombier cgen(l, Z);
6817edc7532SDavid du Colombier boolgen(r, true, nn);
6827edc7532SDavid du Colombier break;
6837edc7532SDavid du Colombier
6847edc7532SDavid du Colombier case ONOT:
6857edc7532SDavid du Colombier boolgen(l, !true, nn);
6867edc7532SDavid du Colombier break;
6877edc7532SDavid du Colombier
6887edc7532SDavid du Colombier case OCOND:
6897edc7532SDavid du Colombier bcgen(l, 1);
6907edc7532SDavid du Colombier p1 = p;
6917edc7532SDavid du Colombier bcgen(r->left, true);
6927edc7532SDavid du Colombier p2 = p;
6937edc7532SDavid du Colombier gbranch(OGOTO);
6947edc7532SDavid du Colombier patch(p1, pc);
6957edc7532SDavid du Colombier p1 = p;
6967edc7532SDavid du Colombier bcgen(r->right, !true);
6977edc7532SDavid du Colombier patch(p2, pc);
6987edc7532SDavid du Colombier p2 = p;
6997edc7532SDavid du Colombier gbranch(OGOTO);
7007edc7532SDavid du Colombier patch(p1, pc);
7017edc7532SDavid du Colombier patch(p2, pc);
7027edc7532SDavid du Colombier goto com;
7037edc7532SDavid du Colombier
7047edc7532SDavid du Colombier case OANDAND:
7057edc7532SDavid du Colombier if(!true)
7067edc7532SDavid du Colombier goto caseor;
7077edc7532SDavid du Colombier
7087edc7532SDavid du Colombier caseand:
7097edc7532SDavid du Colombier bcgen(l, true);
7107edc7532SDavid du Colombier p1 = p;
7117edc7532SDavid du Colombier bcgen(r, !true);
7127edc7532SDavid du Colombier p2 = p;
7137edc7532SDavid du Colombier patch(p1, pc);
7147edc7532SDavid du Colombier gbranch(OGOTO);
7157edc7532SDavid du Colombier patch(p2, pc);
7167edc7532SDavid du Colombier goto com;
7177edc7532SDavid du Colombier
7187edc7532SDavid du Colombier case OOROR:
7197edc7532SDavid du Colombier if(!true)
7207edc7532SDavid du Colombier goto caseand;
7217edc7532SDavid du Colombier
7227edc7532SDavid du Colombier caseor:
7237edc7532SDavid du Colombier bcgen(l, !true);
7247edc7532SDavid du Colombier p1 = p;
7257edc7532SDavid du Colombier bcgen(r, !true);
7267edc7532SDavid du Colombier p2 = p;
7277edc7532SDavid du Colombier gbranch(OGOTO);
7287edc7532SDavid du Colombier patch(p1, pc);
7297edc7532SDavid du Colombier patch(p2, pc);
7307edc7532SDavid du Colombier goto com;
7317edc7532SDavid du Colombier
7327edc7532SDavid du Colombier case OEQ:
7337edc7532SDavid du Colombier case ONE:
7347edc7532SDavid du Colombier case OLE:
7357edc7532SDavid du Colombier case OLT:
7367edc7532SDavid du Colombier case OGE:
7377edc7532SDavid du Colombier case OGT:
7387edc7532SDavid du Colombier case OHI:
7397edc7532SDavid du Colombier case OHS:
7407edc7532SDavid du Colombier case OLO:
7417edc7532SDavid du Colombier case OLS:
7427edc7532SDavid du Colombier o = n->op;
7437edc7532SDavid du Colombier if(true)
7447edc7532SDavid du Colombier o = comrel[relindex(o)];
7457edc7532SDavid du Colombier if(l->complex >= FNX && r->complex >= FNX) {
7467edc7532SDavid du Colombier regret(&nod, r);
7477edc7532SDavid du Colombier cgen(r, &nod);
7487edc7532SDavid du Colombier regsalloc(&nod1, r);
7497edc7532SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
7507edc7532SDavid du Colombier regfree(&nod);
7517edc7532SDavid du Colombier nod = *n;
7527edc7532SDavid du Colombier nod.right = &nod1;
7537edc7532SDavid du Colombier boolgen(&nod, true, nn);
7547edc7532SDavid du Colombier break;
7557edc7532SDavid du Colombier }
7567edc7532SDavid du Colombier if(nn != Z && !typefd[l->type->etype]) {
7577edc7532SDavid du Colombier if(l->complex >= r->complex) {
7587edc7532SDavid du Colombier regalloc(&nod1, l, nn);
7597edc7532SDavid du Colombier cgen(l, &nod1);
7607edc7532SDavid du Colombier regalloc(&nod, r, Z);
7617edc7532SDavid du Colombier cgen(r, &nod);
7627edc7532SDavid du Colombier } else {
7637edc7532SDavid du Colombier regalloc(&nod, r, nn);
7647edc7532SDavid du Colombier cgen(r, &nod);
7657edc7532SDavid du Colombier regalloc(&nod1, l, Z);
7667edc7532SDavid du Colombier cgen(l, &nod1);
7677edc7532SDavid du Colombier }
7687edc7532SDavid du Colombier switch(o) {
7697edc7532SDavid du Colombier case OEQ:
7707edc7532SDavid du Colombier gopcode(OSUB, &nod1, &nod, &nod);
7717edc7532SDavid du Colombier gopcode(OCOND, &nod, nodconst(0), &nod);
7727edc7532SDavid du Colombier break;
7737edc7532SDavid du Colombier case ONE:
7747edc7532SDavid du Colombier gopcode(OSUB, &nod1, &nod, &nod);
7757edc7532SDavid du Colombier gopcode(OCOND, nodconst(1), &nod, &nod);
7767edc7532SDavid du Colombier break;
7777edc7532SDavid du Colombier case OLE:
7787edc7532SDavid du Colombier gopcode(OCOMMA, &nod1, &nod, &nod);
7797edc7532SDavid du Colombier break;
7807edc7532SDavid du Colombier case OGT:
7817edc7532SDavid du Colombier gopcode(OCOMMA, &nod1, &nod, &nod);
7827edc7532SDavid du Colombier gopcode(OXOR, nodconst(1), &nod, &nod);
7837edc7532SDavid du Colombier break;
7847edc7532SDavid du Colombier case OLT:
7857edc7532SDavid du Colombier gopcode(OCOMMA, &nod, &nod1, &nod);
7867edc7532SDavid du Colombier gopcode(OXOR, nodconst(1), &nod, &nod);
7877edc7532SDavid du Colombier break;
7887edc7532SDavid du Colombier case OGE:
7897edc7532SDavid du Colombier gopcode(OCOMMA, &nod, &nod1, &nod);
7907edc7532SDavid du Colombier break;
7917edc7532SDavid du Colombier case OLS:
7927edc7532SDavid du Colombier gopcode(OCOND, &nod1, &nod, &nod);
7937edc7532SDavid du Colombier break;
7947edc7532SDavid du Colombier case OHI:
7957edc7532SDavid du Colombier gopcode(OCOND, &nod1, &nod, &nod);
7967edc7532SDavid du Colombier gopcode(OXOR, nodconst(1), &nod, &nod);
7977edc7532SDavid du Colombier break;
7987edc7532SDavid du Colombier case OLO:
7997edc7532SDavid du Colombier gopcode(OCOND, &nod, &nod1, &nod);
8007edc7532SDavid du Colombier gopcode(OXOR, nodconst(1), &nod, &nod);
8017edc7532SDavid du Colombier break;
8027edc7532SDavid du Colombier case OHS:
8037edc7532SDavid du Colombier gopcode(OCOND, &nod, &nod1, &nod);
8047edc7532SDavid du Colombier break;
8057edc7532SDavid du Colombier }
8067edc7532SDavid du Colombier gopcode(OAS, &nod, Z, nn);
8077edc7532SDavid du Colombier regfree(&nod);
8087edc7532SDavid du Colombier regfree(&nod1);
8097edc7532SDavid du Colombier break;
8107edc7532SDavid du Colombier }
8117edc7532SDavid du Colombier if(sconst(l)) {
8127edc7532SDavid du Colombier switch(o) {
8137edc7532SDavid du Colombier default:
8147edc7532SDavid du Colombier if(l->vconst != 0)
8157edc7532SDavid du Colombier break;
8167edc7532SDavid du Colombier
8177edc7532SDavid du Colombier case OGT:
8187edc7532SDavid du Colombier case OHI:
8197edc7532SDavid du Colombier case OLE:
8207edc7532SDavid du Colombier case OLS:
8217edc7532SDavid du Colombier regalloc(&nod, r, nn);
8227edc7532SDavid du Colombier cgen(r, &nod);
8237edc7532SDavid du Colombier gopcode(o, l, &nod, Z);
8247edc7532SDavid du Colombier regfree(&nod);
8257edc7532SDavid du Colombier goto com;
8267edc7532SDavid du Colombier }
8277edc7532SDavid du Colombier }
8287edc7532SDavid du Colombier if(sconst(r)) {
8297edc7532SDavid du Colombier switch(o) {
8307edc7532SDavid du Colombier default:
8317edc7532SDavid du Colombier if(r->vconst != 0)
8327edc7532SDavid du Colombier break;
8337edc7532SDavid du Colombier
8347edc7532SDavid du Colombier case OGE:
8357edc7532SDavid du Colombier case OHS:
8367edc7532SDavid du Colombier case OLT:
8377edc7532SDavid du Colombier case OLO:
8387edc7532SDavid du Colombier regalloc(&nod, l, nn);
8397edc7532SDavid du Colombier cgen(l, &nod);
8407edc7532SDavid du Colombier gopcode(o, &nod, r, Z);
8417edc7532SDavid du Colombier regfree(&nod);
8427edc7532SDavid du Colombier goto com;
8437edc7532SDavid du Colombier }
8447edc7532SDavid du Colombier }
8457edc7532SDavid du Colombier if(l->complex >= r->complex) {
8467edc7532SDavid du Colombier regalloc(&nod1, l, nn);
8477edc7532SDavid du Colombier cgen(l, &nod1);
8487edc7532SDavid du Colombier regalloc(&nod, r, Z);
8497edc7532SDavid du Colombier cgen(r, &nod);
8507edc7532SDavid du Colombier } else {
8517edc7532SDavid du Colombier regalloc(&nod, r, nn);
8527edc7532SDavid du Colombier cgen(r, &nod);
8537edc7532SDavid du Colombier regalloc(&nod1, l, Z);
8547edc7532SDavid du Colombier cgen(l, &nod1);
8557edc7532SDavid du Colombier }
8567edc7532SDavid du Colombier gopcode(o, &nod1, &nod, Z);
8577edc7532SDavid du Colombier regfree(&nod);
8587edc7532SDavid du Colombier regfree(&nod1);
8597edc7532SDavid du Colombier
8607edc7532SDavid du Colombier com:
8617edc7532SDavid du Colombier if(nn != Z) {
8627edc7532SDavid du Colombier p1 = p;
8637edc7532SDavid du Colombier gopcode(OAS, nodconst(1), Z, nn);
8647edc7532SDavid du Colombier gbranch(OGOTO);
8657edc7532SDavid du Colombier p2 = p;
8667edc7532SDavid du Colombier patch(p1, pc);
8677edc7532SDavid du Colombier gopcode(OAS, nodconst(0), Z, nn);
8687edc7532SDavid du Colombier patch(p2, pc);
8697edc7532SDavid du Colombier }
8707edc7532SDavid du Colombier break;
8717edc7532SDavid du Colombier }
8727edc7532SDavid du Colombier cursafe = curs;
8737edc7532SDavid du Colombier }
8747edc7532SDavid du Colombier
8757edc7532SDavid du Colombier void
sugen(Node * n,Node * nn,long w)8767edc7532SDavid du Colombier sugen(Node *n, Node *nn, long w)
8777edc7532SDavid du Colombier {
8787edc7532SDavid du Colombier Prog *p1;
8797edc7532SDavid du Colombier Node nod0, nod1, nod2, nod3, nod4, *l, *r;
8807edc7532SDavid du Colombier Type *t;
8817edc7532SDavid du Colombier long pc1;
8827edc7532SDavid du Colombier int i, m, c;
8837edc7532SDavid du Colombier
8847edc7532SDavid du Colombier if(n == Z || n->type == T)
8857edc7532SDavid du Colombier return;
8867edc7532SDavid du Colombier if(debug['g']) {
8877edc7532SDavid du Colombier prtree(nn, "sugen lhs");
8887edc7532SDavid du Colombier prtree(n, "sugen");
8897edc7532SDavid du Colombier }
8907edc7532SDavid du Colombier if(nn == nodrat)
8917edc7532SDavid du Colombier if(w > nrathole)
8927edc7532SDavid du Colombier nrathole = w;
8937edc7532SDavid du Colombier switch(n->op) {
8947edc7532SDavid du Colombier case OIND:
8957edc7532SDavid du Colombier if(nn == Z) {
8967edc7532SDavid du Colombier nullwarn(n->left, Z);
8977edc7532SDavid du Colombier break;
8987edc7532SDavid du Colombier }
8997edc7532SDavid du Colombier
9007edc7532SDavid du Colombier default:
9017edc7532SDavid du Colombier goto copy;
9027edc7532SDavid du Colombier
9037edc7532SDavid du Colombier case ODOT:
9047edc7532SDavid du Colombier l = n->left;
9057edc7532SDavid du Colombier sugen(l, nodrat, l->type->width);
9067edc7532SDavid du Colombier if(nn != Z) {
9077edc7532SDavid du Colombier warn(n, "non-interruptable temporary");
9087edc7532SDavid du Colombier nod1 = *nodrat;
9097edc7532SDavid du Colombier r = n->right;
9107edc7532SDavid du Colombier if(!r || r->op != OCONST) {
9117edc7532SDavid du Colombier diag(n, "DOT and no offset");
9127edc7532SDavid du Colombier break;
9137edc7532SDavid du Colombier }
9147edc7532SDavid du Colombier nod1.xoffset += (long)r->vconst;
9157edc7532SDavid du Colombier nod1.type = n->type;
9167edc7532SDavid du Colombier sugen(&nod1, nn, w);
9177edc7532SDavid du Colombier }
9187edc7532SDavid du Colombier break;
9197edc7532SDavid du Colombier
9207edc7532SDavid du Colombier case OSTRUCT:
9217edc7532SDavid du Colombier /*
922*cd2352d6SDavid du Colombier * rewrite so lhs has no side effects
9237edc7532SDavid du Colombier */
924*cd2352d6SDavid du Colombier if(nn != Z && side(nn)) {
9257edc7532SDavid du Colombier nod1 = *n;
9267edc7532SDavid du Colombier nod1.type = typ(TIND, n->type);
927*cd2352d6SDavid du Colombier regalloc(&nod2, &nod1, Z);
9287edc7532SDavid du Colombier lcgen(nn, &nod2);
9297edc7532SDavid du Colombier regsalloc(&nod0, &nod1);
9307edc7532SDavid du Colombier gopcode(OAS, &nod2, Z, &nod0);
9317edc7532SDavid du Colombier regfree(&nod2);
9327edc7532SDavid du Colombier
9337edc7532SDavid du Colombier nod1 = *n;
9347edc7532SDavid du Colombier nod1.op = OIND;
9357edc7532SDavid du Colombier nod1.left = &nod0;
9367edc7532SDavid du Colombier nod1.right = Z;
9377edc7532SDavid du Colombier nod1.complex = 1;
9387edc7532SDavid du Colombier
9397edc7532SDavid du Colombier sugen(n, &nod1, w);
9407edc7532SDavid du Colombier return;
9417edc7532SDavid du Colombier }
9427edc7532SDavid du Colombier
9437edc7532SDavid du Colombier r = n->left;
9447edc7532SDavid du Colombier for(t = n->type->link; t != T; t = t->down) {
9457edc7532SDavid du Colombier l = r;
9467edc7532SDavid du Colombier if(r->op == OLIST) {
9477edc7532SDavid du Colombier l = r->left;
9487edc7532SDavid du Colombier r = r->right;
9497edc7532SDavid du Colombier }
9507edc7532SDavid du Colombier if(nn == Z) {
9517edc7532SDavid du Colombier cgen(l, nn);
9527edc7532SDavid du Colombier continue;
9537edc7532SDavid du Colombier }
9547edc7532SDavid du Colombier /*
9557edc7532SDavid du Colombier * hand craft *(&nn + o) = l
9567edc7532SDavid du Colombier */
9577edc7532SDavid du Colombier nod0 = znode;
9587edc7532SDavid du Colombier nod0.op = OAS;
9597edc7532SDavid du Colombier nod0.type = t;
9607edc7532SDavid du Colombier nod0.left = &nod1;
9617edc7532SDavid du Colombier nod0.right = l;
9627edc7532SDavid du Colombier
9637edc7532SDavid du Colombier nod1 = znode;
9647edc7532SDavid du Colombier nod1.op = OIND;
9657edc7532SDavid du Colombier nod1.type = t;
9667edc7532SDavid du Colombier nod1.left = &nod2;
9677edc7532SDavid du Colombier
9687edc7532SDavid du Colombier nod2 = znode;
9697edc7532SDavid du Colombier nod2.op = OADD;
9707edc7532SDavid du Colombier nod2.type = typ(TIND, t);
9717edc7532SDavid du Colombier nod2.left = &nod3;
9727edc7532SDavid du Colombier nod2.right = &nod4;
9737edc7532SDavid du Colombier
9747edc7532SDavid du Colombier nod3 = znode;
9757edc7532SDavid du Colombier nod3.op = OADDR;
9767edc7532SDavid du Colombier nod3.type = nod2.type;
9777edc7532SDavid du Colombier nod3.left = nn;
9787edc7532SDavid du Colombier
9797edc7532SDavid du Colombier nod4 = znode;
9807edc7532SDavid du Colombier nod4.op = OCONST;
9817edc7532SDavid du Colombier nod4.type = nod2.type;
9827edc7532SDavid du Colombier nod4.vconst = t->offset;
9837edc7532SDavid du Colombier
9847edc7532SDavid du Colombier ccom(&nod0);
9857edc7532SDavid du Colombier acom(&nod0);
9867edc7532SDavid du Colombier xcom(&nod0);
9877edc7532SDavid du Colombier nod0.addable = 0;
9887edc7532SDavid du Colombier
9897edc7532SDavid du Colombier cgen(&nod0, Z);
9907edc7532SDavid du Colombier }
9917edc7532SDavid du Colombier break;
9927edc7532SDavid du Colombier
9937edc7532SDavid du Colombier case OAS:
9947edc7532SDavid du Colombier if(nn == Z) {
9957edc7532SDavid du Colombier if(n->addable < INDEXED)
9967edc7532SDavid du Colombier sugen(n->right, n->left, w);
9977edc7532SDavid du Colombier break;
9987edc7532SDavid du Colombier }
9997edc7532SDavid du Colombier sugen(n->right, nodrat, w);
10007edc7532SDavid du Colombier warn(n, "non-interruptable temporary");
10017edc7532SDavid du Colombier sugen(nodrat, n->left, w);
10027edc7532SDavid du Colombier sugen(nodrat, nn, w);
10037edc7532SDavid du Colombier break;
10047edc7532SDavid du Colombier
10057edc7532SDavid du Colombier case OFUNC:
10067edc7532SDavid du Colombier if(nn == Z) {
10077edc7532SDavid du Colombier sugen(n, nodrat, w);
10087edc7532SDavid du Colombier break;
10097edc7532SDavid du Colombier }
10107edc7532SDavid du Colombier if(nn->op != OIND) {
10117edc7532SDavid du Colombier nn = new1(OADDR, nn, Z);
10127edc7532SDavid du Colombier nn->type = types[TIND];
10137edc7532SDavid du Colombier nn->addable = 0;
10147edc7532SDavid du Colombier } else
10157edc7532SDavid du Colombier nn = nn->left;
10167edc7532SDavid du Colombier n = new(OFUNC, n->left, new(OLIST, nn, n->right));
10177edc7532SDavid du Colombier n->type = types[TVOID];
10187edc7532SDavid du Colombier n->left->type = types[TVOID];
10197edc7532SDavid du Colombier cgen(n, Z);
10207edc7532SDavid du Colombier break;
10217edc7532SDavid du Colombier
10227edc7532SDavid du Colombier case OCOND:
10237edc7532SDavid du Colombier bcgen(n->left, 1);
10247edc7532SDavid du Colombier p1 = p;
10257edc7532SDavid du Colombier sugen(n->right->left, nn, w);
10267edc7532SDavid du Colombier gbranch(OGOTO);
10277edc7532SDavid du Colombier patch(p1, pc);
10287edc7532SDavid du Colombier p1 = p;
10297edc7532SDavid du Colombier sugen(n->right->right, nn, w);
10307edc7532SDavid du Colombier patch(p1, pc);
10317edc7532SDavid du Colombier break;
10327edc7532SDavid du Colombier
10337edc7532SDavid du Colombier case OCOMMA:
10347edc7532SDavid du Colombier cgen(n->left, Z);
10357edc7532SDavid du Colombier sugen(n->right, nn, w);
10367edc7532SDavid du Colombier break;
10377edc7532SDavid du Colombier }
10387edc7532SDavid du Colombier return;
10397edc7532SDavid du Colombier
10407edc7532SDavid du Colombier copy:
10417edc7532SDavid du Colombier if(nn == Z)
10427edc7532SDavid du Colombier return;
10437edc7532SDavid du Colombier if(n->complex >= FNX && nn->complex >= FNX) {
10447edc7532SDavid du Colombier t = nn->type;
10457edc7532SDavid du Colombier nn->type = types[TLONG];
10467edc7532SDavid du Colombier regialloc(&nod1, nn, Z);
10477edc7532SDavid du Colombier lcgen(nn, &nod1);
10487edc7532SDavid du Colombier regsalloc(&nod2, nn);
10497edc7532SDavid du Colombier nn->type = t;
10507edc7532SDavid du Colombier
10517edc7532SDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
10527edc7532SDavid du Colombier regfree(&nod1);
10537edc7532SDavid du Colombier
10547edc7532SDavid du Colombier nod2.type = typ(TIND, t);
10557edc7532SDavid du Colombier
10567edc7532SDavid du Colombier nod1 = nod2;
10577edc7532SDavid du Colombier nod1.op = OIND;
10587edc7532SDavid du Colombier nod1.left = &nod2;
10597edc7532SDavid du Colombier nod1.right = Z;
10607edc7532SDavid du Colombier nod1.complex = 1;
10617edc7532SDavid du Colombier nod1.type = t;
10627edc7532SDavid du Colombier
10637edc7532SDavid du Colombier sugen(n, &nod1, w);
10647edc7532SDavid du Colombier return;
10657edc7532SDavid du Colombier }
10667edc7532SDavid du Colombier
10677edc7532SDavid du Colombier if(n->complex > nn->complex) {
10687edc7532SDavid du Colombier t = n->type;
10697edc7532SDavid du Colombier n->type = types[TVLONG];
10707edc7532SDavid du Colombier reglcgen(&nod1, n, Z);
10717edc7532SDavid du Colombier n->type = t;
10727edc7532SDavid du Colombier
10737edc7532SDavid du Colombier t = nn->type;
10747edc7532SDavid du Colombier nn->type = types[TVLONG];
10757edc7532SDavid du Colombier reglcgen(&nod2, nn, Z);
10767edc7532SDavid du Colombier nn->type = t;
10777edc7532SDavid du Colombier } else {
10787edc7532SDavid du Colombier t = nn->type;
10797edc7532SDavid du Colombier nn->type = types[TVLONG];
10807edc7532SDavid du Colombier reglcgen(&nod2, nn, Z);
10817edc7532SDavid du Colombier nn->type = t;
10827edc7532SDavid du Colombier
10837edc7532SDavid du Colombier t = n->type;
10847edc7532SDavid du Colombier n->type = types[TVLONG];
10857edc7532SDavid du Colombier reglcgen(&nod1, n, Z);
10867edc7532SDavid du Colombier n->type = t;
10877edc7532SDavid du Colombier }
10887edc7532SDavid du Colombier
10897edc7532SDavid du Colombier w /= SZ_VLONG;
10907edc7532SDavid du Colombier if(w <= 5) {
10917edc7532SDavid du Colombier layout(&nod1, &nod2, w, 0, Z);
10927edc7532SDavid du Colombier goto out;
10937edc7532SDavid du Colombier }
10947edc7532SDavid du Colombier
10957edc7532SDavid du Colombier /*
10967edc7532SDavid du Colombier * minimize space for unrolling loop
10977edc7532SDavid du Colombier * 3,4,5 times. (6 or more is never minimum)
10987edc7532SDavid du Colombier * if small structure, try 2 also.
10997edc7532SDavid du Colombier */
11007edc7532SDavid du Colombier c = 0; /* set */
11017edc7532SDavid du Colombier m = 100;
11027edc7532SDavid du Colombier i = 3;
11037edc7532SDavid du Colombier if(w <= 15)
11047edc7532SDavid du Colombier i = 2;
11057edc7532SDavid du Colombier for(; i<=5; i++)
11067edc7532SDavid du Colombier if(i + w%i <= m) {
11077edc7532SDavid du Colombier c = i;
11087edc7532SDavid du Colombier m = c + w%c;
11097edc7532SDavid du Colombier }
11107edc7532SDavid du Colombier
11117edc7532SDavid du Colombier regalloc(&nod3, ®node, Z);
11127edc7532SDavid du Colombier layout(&nod1, &nod2, w%c, w/c, &nod3);
11137edc7532SDavid du Colombier
11147edc7532SDavid du Colombier pc1 = pc;
11157edc7532SDavid du Colombier layout(&nod1, &nod2, c, 0, Z);
11167edc7532SDavid du Colombier
11177edc7532SDavid du Colombier gopcode(OSUB, nodconst(1), Z, &nod3);
11187edc7532SDavid du Colombier nod1.op = OREGISTER;
11197edc7532SDavid du Colombier gopcode(OADD, nodconst(c*SZ_VLONG), Z, &nod1);
11207edc7532SDavid du Colombier nod2.op = OREGISTER;
11217edc7532SDavid du Colombier gopcode(OADD, nodconst(c*SZ_VLONG), Z, &nod2);
11227edc7532SDavid du Colombier
11237edc7532SDavid du Colombier gopcode(OEQ, &nod3, Z, Z);
11247edc7532SDavid du Colombier p->as = ABGTZ;
11257edc7532SDavid du Colombier patch(p, pc1);
11267edc7532SDavid du Colombier
11277edc7532SDavid du Colombier regfree(&nod3);
11287edc7532SDavid du Colombier out:
11297edc7532SDavid du Colombier regfree(&nod1);
11307edc7532SDavid du Colombier regfree(&nod2);
11317edc7532SDavid du Colombier }
11327edc7532SDavid du Colombier
11337edc7532SDavid du Colombier void
layout(Node * f,Node * t,int c,int cv,Node * cn)11347edc7532SDavid du Colombier layout(Node *f, Node *t, int c, int cv, Node *cn)
11357edc7532SDavid du Colombier {
11367edc7532SDavid du Colombier Node t1, t2;
11377edc7532SDavid du Colombier
11387edc7532SDavid du Colombier while(c > 3) {
11397edc7532SDavid du Colombier layout(f, t, 2, 0, Z);
11407edc7532SDavid du Colombier c -= 2;
11417edc7532SDavid du Colombier }
11427edc7532SDavid du Colombier
11437edc7532SDavid du Colombier regalloc(&t1, ®node, Z);
11447edc7532SDavid du Colombier regalloc(&t2, ®node, Z);
11457edc7532SDavid du Colombier t1.type = types[TVLONG];
11467edc7532SDavid du Colombier t2.type = types[TVLONG];
11477edc7532SDavid du Colombier if(c > 0) {
11487edc7532SDavid du Colombier gopcode(OAS, f, Z, &t1);
11497edc7532SDavid du Colombier f->xoffset += SZ_VLONG;
11507edc7532SDavid du Colombier }
11517edc7532SDavid du Colombier if(cn != Z)
11527edc7532SDavid du Colombier gopcode(OAS, nodconst(cv), Z, cn);
11537edc7532SDavid du Colombier if(c > 1) {
11547edc7532SDavid du Colombier gopcode(OAS, f, Z, &t2);
11557edc7532SDavid du Colombier f->xoffset += SZ_VLONG;
11567edc7532SDavid du Colombier }
11577edc7532SDavid du Colombier if(c > 0) {
11587edc7532SDavid du Colombier gopcode(OAS, &t1, Z, t);
11597edc7532SDavid du Colombier t->xoffset += SZ_VLONG;
11607edc7532SDavid du Colombier }
11617edc7532SDavid du Colombier if(c > 2) {
11627edc7532SDavid du Colombier gopcode(OAS, f, Z, &t1);
11637edc7532SDavid du Colombier f->xoffset += SZ_VLONG;
11647edc7532SDavid du Colombier }
11657edc7532SDavid du Colombier if(c > 1) {
11667edc7532SDavid du Colombier gopcode(OAS, &t2, Z, t);
11677edc7532SDavid du Colombier t->xoffset += SZ_VLONG;
11687edc7532SDavid du Colombier }
11697edc7532SDavid du Colombier if(c > 2) {
11707edc7532SDavid du Colombier gopcode(OAS, &t1, Z, t);
11717edc7532SDavid du Colombier t->xoffset += SZ_VLONG;
11727edc7532SDavid du Colombier }
11737edc7532SDavid du Colombier regfree(&t1);
11747edc7532SDavid du Colombier regfree(&t2);
11757edc7532SDavid du Colombier }
1176