13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier
33e12c5d1SDavid du Colombier void
cgen(Node * n,Node * nn)43e12c5d1SDavid du Colombier cgen(Node *n, Node *nn)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier Node *l, *r;
73e12c5d1SDavid du Colombier Prog *p1;
83e12c5d1SDavid du Colombier Node nod, nod1, nod2, nod3, nod4;
93e12c5d1SDavid du Colombier int o;
103e12c5d1SDavid du Colombier long v, curs;
113e12c5d1SDavid du Colombier
123e12c5d1SDavid du Colombier if(debug['g']) {
133e12c5d1SDavid du Colombier prtree(nn, "cgen lhs");
143e12c5d1SDavid du Colombier prtree(n, "cgen");
153e12c5d1SDavid du Colombier }
163e12c5d1SDavid du Colombier if(n == Z || n->type == T)
173e12c5d1SDavid du Colombier return;
187dd7cddfSDavid du Colombier if(typesuv[n->type->etype]) {
193e12c5d1SDavid du Colombier sugen(n, nn, n->type->width);
203e12c5d1SDavid du Colombier return;
213e12c5d1SDavid du Colombier }
227dd7cddfSDavid du Colombier l = n->left;
237dd7cddfSDavid du Colombier r = n->right;
247dd7cddfSDavid du Colombier o = n->op;
257dd7cddfSDavid du Colombier if(n->addable >= INDEXED) {
267dd7cddfSDavid du Colombier if(nn == Z) {
277dd7cddfSDavid du Colombier switch(o) {
287dd7cddfSDavid du Colombier default:
297dd7cddfSDavid du Colombier nullwarn(Z, Z);
307dd7cddfSDavid du Colombier break;
317dd7cddfSDavid du Colombier case OINDEX:
327dd7cddfSDavid du Colombier nullwarn(l, r);
337dd7cddfSDavid du Colombier break;
347dd7cddfSDavid du Colombier }
357dd7cddfSDavid du Colombier return;
367dd7cddfSDavid du Colombier }
373e12c5d1SDavid du Colombier gmove(n, nn);
383e12c5d1SDavid du Colombier return;
393e12c5d1SDavid du Colombier }
403e12c5d1SDavid du Colombier curs = cursafe;
413e12c5d1SDavid du Colombier
423e12c5d1SDavid du Colombier if(n->complex >= FNX)
433e12c5d1SDavid du Colombier if(l->complex >= FNX)
443e12c5d1SDavid du Colombier if(r != Z && r->complex >= FNX)
453e12c5d1SDavid du Colombier switch(o) {
463e12c5d1SDavid du Colombier default:
473e12c5d1SDavid du Colombier regret(&nod, r);
483e12c5d1SDavid du Colombier cgen(r, &nod);
493e12c5d1SDavid du Colombier
503e12c5d1SDavid du Colombier regsalloc(&nod1, r);
513e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
523e12c5d1SDavid du Colombier
533e12c5d1SDavid du Colombier regfree(&nod);
543e12c5d1SDavid du Colombier nod = *n;
553e12c5d1SDavid du Colombier nod.right = &nod1;
563e12c5d1SDavid du Colombier cgen(&nod, nn);
573e12c5d1SDavid du Colombier return;
583e12c5d1SDavid du Colombier
593e12c5d1SDavid du Colombier case OFUNC:
603e12c5d1SDavid du Colombier case OCOMMA:
613e12c5d1SDavid du Colombier case OANDAND:
623e12c5d1SDavid du Colombier case OOROR:
633e12c5d1SDavid du Colombier case OCOND:
643e12c5d1SDavid du Colombier case ODOT:
653e12c5d1SDavid du Colombier break;
663e12c5d1SDavid du Colombier }
673e12c5d1SDavid du Colombier
683e12c5d1SDavid du Colombier switch(o) {
693e12c5d1SDavid du Colombier default:
703e12c5d1SDavid du Colombier diag(n, "unknown op in cgen: %O", o);
713e12c5d1SDavid du Colombier break;
723e12c5d1SDavid du Colombier
733e12c5d1SDavid du Colombier case OAS:
743e12c5d1SDavid du Colombier if(l->op == OBIT)
753e12c5d1SDavid du Colombier goto bitas;
763e12c5d1SDavid du Colombier if(l->addable >= INDEXED) {
773e12c5d1SDavid du Colombier if(nn != Z || r->addable < INDEXED) {
787dd7cddfSDavid du Colombier if(r->complex >= FNX && nn == Z)
797dd7cddfSDavid du Colombier regret(&nod, r);
807dd7cddfSDavid du Colombier else
813e12c5d1SDavid du Colombier regalloc(&nod, r, nn);
823e12c5d1SDavid du Colombier cgen(r, &nod);
833e12c5d1SDavid du Colombier gmove(&nod, l);
847dd7cddfSDavid du Colombier if(nn != Z)
857dd7cddfSDavid du Colombier gmove(&nod, nn);
863e12c5d1SDavid du Colombier regfree(&nod);
873e12c5d1SDavid du Colombier } else
883e12c5d1SDavid du Colombier gmove(r, l);
893e12c5d1SDavid du Colombier break;
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier if(l->complex >= r->complex) {
923e12c5d1SDavid du Colombier reglcgen(&nod1, l, Z);
933e12c5d1SDavid du Colombier if(r->addable >= INDEXED) {
943e12c5d1SDavid du Colombier gmove(r, &nod1);
953e12c5d1SDavid du Colombier if(nn != Z)
963e12c5d1SDavid du Colombier gmove(r, nn);
973e12c5d1SDavid du Colombier regfree(&nod1);
983e12c5d1SDavid du Colombier break;
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier regalloc(&nod, r, nn);
1013e12c5d1SDavid du Colombier cgen(r, &nod);
1023e12c5d1SDavid du Colombier } else {
1033e12c5d1SDavid du Colombier regalloc(&nod, r, nn);
1043e12c5d1SDavid du Colombier cgen(r, &nod);
1053e12c5d1SDavid du Colombier reglcgen(&nod1, l, Z);
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier gmove(&nod, &nod1);
1083e12c5d1SDavid du Colombier regfree(&nod);
1093e12c5d1SDavid du Colombier regfree(&nod1);
1103e12c5d1SDavid du Colombier break;
1113e12c5d1SDavid du Colombier
1123e12c5d1SDavid du Colombier bitas:
1133e12c5d1SDavid du Colombier n = l->left;
1143e12c5d1SDavid du Colombier regalloc(&nod, r, nn);
1153e12c5d1SDavid du Colombier if(l->complex >= r->complex) {
1163e12c5d1SDavid du Colombier reglcgen(&nod1, n, Z);
1173e12c5d1SDavid du Colombier cgen(r, &nod);
1183e12c5d1SDavid du Colombier } else {
1193e12c5d1SDavid du Colombier cgen(r, &nod);
1203e12c5d1SDavid du Colombier reglcgen(&nod1, n, Z);
1213e12c5d1SDavid du Colombier }
1223e12c5d1SDavid du Colombier regalloc(&nod2, n, Z);
1233e12c5d1SDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
1243e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
1253e12c5d1SDavid du Colombier break;
1263e12c5d1SDavid du Colombier
1273e12c5d1SDavid du Colombier case OBIT:
1283e12c5d1SDavid du Colombier if(nn == Z) {
1293e12c5d1SDavid du Colombier nullwarn(l, Z);
1303e12c5d1SDavid du Colombier break;
1313e12c5d1SDavid du Colombier }
1323e12c5d1SDavid du Colombier bitload(n, &nod, Z, Z, nn);
1333e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, nn);
1343e12c5d1SDavid du Colombier regfree(&nod);
1353e12c5d1SDavid du Colombier break;
1363e12c5d1SDavid du Colombier
1373e12c5d1SDavid du Colombier case OADD:
1383e12c5d1SDavid du Colombier case OSUB:
1393e12c5d1SDavid du Colombier case OAND:
1403e12c5d1SDavid du Colombier case OOR:
1413e12c5d1SDavid du Colombier case OXOR:
1423e12c5d1SDavid du Colombier case OLSHR:
1433e12c5d1SDavid du Colombier case OASHL:
1443e12c5d1SDavid du Colombier case OASHR:
1453e12c5d1SDavid du Colombier /*
1463e12c5d1SDavid du Colombier * immediate operands
1473e12c5d1SDavid du Colombier */
1483e12c5d1SDavid du Colombier if(nn != Z)
1493e12c5d1SDavid du Colombier if(r->op == OCONST)
150219b2ee8SDavid du Colombier if(!typefd[n->type->etype]) {
1513e12c5d1SDavid du Colombier cgen(l, nn);
152219b2ee8SDavid du Colombier if(r->vconst == 0)
1533e12c5d1SDavid du Colombier if(o != OAND)
1543e12c5d1SDavid du Colombier break;
1553e12c5d1SDavid du Colombier if(nn != Z)
1563e12c5d1SDavid du Colombier gopcode(o, r, Z, nn);
1573e12c5d1SDavid du Colombier break;
1583e12c5d1SDavid du Colombier }
1593e12c5d1SDavid du Colombier
1603e12c5d1SDavid du Colombier case OMUL:
1613e12c5d1SDavid du Colombier case OLMUL:
1623e12c5d1SDavid du Colombier case OLDIV:
1633e12c5d1SDavid du Colombier case OLMOD:
1643e12c5d1SDavid du Colombier case ODIV:
1653e12c5d1SDavid du Colombier case OMOD:
1663e12c5d1SDavid du Colombier if(nn == Z) {
1673e12c5d1SDavid du Colombier nullwarn(l, r);
1683e12c5d1SDavid du Colombier break;
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier if(o == OMUL || o == OLMUL) {
1713e12c5d1SDavid du Colombier if(mulcon(n, nn))
1723e12c5d1SDavid du Colombier break;
1733e12c5d1SDavid du Colombier if(debug['M'])
1743e12c5d1SDavid du Colombier print("%L multiply\n", n->lineno);
1753e12c5d1SDavid du Colombier }
1763e12c5d1SDavid du Colombier if(l->complex >= r->complex) {
1773e12c5d1SDavid du Colombier regalloc(&nod, l, nn);
1783e12c5d1SDavid du Colombier cgen(l, &nod);
1793e12c5d1SDavid du Colombier regalloc(&nod1, r, Z);
1803e12c5d1SDavid du Colombier cgen(r, &nod1);
1813e12c5d1SDavid du Colombier gopcode(o, &nod1, Z, &nod);
1823e12c5d1SDavid du Colombier } else {
1833e12c5d1SDavid du Colombier regalloc(&nod, r, nn);
1843e12c5d1SDavid du Colombier cgen(r, &nod);
1853e12c5d1SDavid du Colombier regalloc(&nod1, l, Z);
1863e12c5d1SDavid du Colombier cgen(l, &nod1);
1873e12c5d1SDavid du Colombier gopcode(o, &nod, &nod1, &nod);
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, nn);
1903e12c5d1SDavid du Colombier regfree(&nod);
1913e12c5d1SDavid du Colombier regfree(&nod1);
1923e12c5d1SDavid du Colombier break;
1933e12c5d1SDavid du Colombier
1943e12c5d1SDavid du Colombier case OASLSHR:
1953e12c5d1SDavid du Colombier case OASASHL:
1963e12c5d1SDavid du Colombier case OASASHR:
1973e12c5d1SDavid du Colombier case OASAND:
1983e12c5d1SDavid du Colombier case OASADD:
1993e12c5d1SDavid du Colombier case OASSUB:
2003e12c5d1SDavid du Colombier case OASXOR:
2013e12c5d1SDavid du Colombier case OASOR:
2023e12c5d1SDavid du Colombier if(l->op == OBIT)
2033e12c5d1SDavid du Colombier goto asbitop;
2043e12c5d1SDavid du Colombier if(r->op == OCONST)
205219b2ee8SDavid du Colombier if(!typefd[n->type->etype]) {
2063e12c5d1SDavid du Colombier if(l->addable < INDEXED)
2073e12c5d1SDavid du Colombier reglcgen(&nod2, l, Z);
2083e12c5d1SDavid du Colombier else
2093e12c5d1SDavid du Colombier nod2 = *l;
2103e12c5d1SDavid du Colombier regalloc(&nod, r, nn);
2113e12c5d1SDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
2123e12c5d1SDavid du Colombier gopcode(o, r, Z, &nod);
2133e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod2);
2143e12c5d1SDavid du Colombier
2153e12c5d1SDavid du Colombier regfree(&nod);
2163e12c5d1SDavid du Colombier if(l->addable < INDEXED)
2173e12c5d1SDavid du Colombier regfree(&nod2);
2183e12c5d1SDavid du Colombier break;
2193e12c5d1SDavid du Colombier }
2203e12c5d1SDavid du Colombier
2213e12c5d1SDavid du Colombier case OASLMUL:
2223e12c5d1SDavid du Colombier case OASLDIV:
2233e12c5d1SDavid du Colombier case OASLMOD:
2243e12c5d1SDavid du Colombier case OASMUL:
2253e12c5d1SDavid du Colombier case OASDIV:
2263e12c5d1SDavid du Colombier case OASMOD:
2273e12c5d1SDavid du Colombier if(l->op == OBIT)
2283e12c5d1SDavid du Colombier goto asbitop;
2293e12c5d1SDavid du Colombier if(l->complex >= r->complex) {
2303e12c5d1SDavid du Colombier if(l->addable < INDEXED)
2313e12c5d1SDavid du Colombier reglcgen(&nod2, l, Z);
2323e12c5d1SDavid du Colombier else
2333e12c5d1SDavid du Colombier nod2 = *l;
234219b2ee8SDavid du Colombier regalloc(&nod, n, nn);
2353e12c5d1SDavid du Colombier cgen(r, &nod);
2363e12c5d1SDavid du Colombier } else {
237219b2ee8SDavid du Colombier regalloc(&nod, n, nn);
2383e12c5d1SDavid du Colombier cgen(r, &nod);
2393e12c5d1SDavid du Colombier if(l->addable < INDEXED)
2403e12c5d1SDavid du Colombier reglcgen(&nod2, l, Z);
2413e12c5d1SDavid du Colombier else
2423e12c5d1SDavid du Colombier nod2 = *l;
2433e12c5d1SDavid du Colombier }
244219b2ee8SDavid du Colombier regalloc(&nod1, n, Z);
2453e12c5d1SDavid du Colombier gopcode(OAS, &nod2, Z, &nod1);
2463e12c5d1SDavid du Colombier gopcode(o, &nod, &nod1, &nod);
2473e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod2);
2483e12c5d1SDavid du Colombier regfree(&nod);
2493e12c5d1SDavid du Colombier regfree(&nod1);
2503e12c5d1SDavid du Colombier if(l->addable < INDEXED)
2513e12c5d1SDavid du Colombier regfree(&nod2);
2523e12c5d1SDavid du Colombier break;
2533e12c5d1SDavid du Colombier
2543e12c5d1SDavid du Colombier asbitop:
2553e12c5d1SDavid du Colombier regalloc(&nod4, n, nn);
2563e12c5d1SDavid du Colombier regalloc(&nod3, r, Z);
2573e12c5d1SDavid du Colombier if(l->complex >= r->complex) {
2583e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
2593e12c5d1SDavid du Colombier cgen(r, &nod3);
2603e12c5d1SDavid du Colombier } else {
2613e12c5d1SDavid du Colombier cgen(r, &nod3);
2623e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
2633e12c5d1SDavid du Colombier }
2643e12c5d1SDavid du Colombier gmove(&nod, &nod4);
2653e12c5d1SDavid du Colombier gopcode(n->op, &nod3, Z, &nod4);
2663e12c5d1SDavid du Colombier regfree(&nod3);
2673e12c5d1SDavid du Colombier gmove(&nod4, &nod);
2683e12c5d1SDavid du Colombier regfree(&nod4);
2693e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
2703e12c5d1SDavid du Colombier break;
2713e12c5d1SDavid du Colombier
2723e12c5d1SDavid du Colombier case OADDR:
2733e12c5d1SDavid du Colombier if(nn == Z) {
2743e12c5d1SDavid du Colombier nullwarn(l, Z);
2753e12c5d1SDavid du Colombier break;
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier lcgen(l, nn);
2783e12c5d1SDavid du Colombier break;
2793e12c5d1SDavid du Colombier
2803e12c5d1SDavid du Colombier case OFUNC:
2813e12c5d1SDavid du Colombier if(l->complex >= FNX) {
2823e12c5d1SDavid du Colombier if(l->op != OIND)
2833e12c5d1SDavid du Colombier diag(n, "bad function call");
2843e12c5d1SDavid du Colombier
2853e12c5d1SDavid du Colombier regret(&nod, l->left);
2863e12c5d1SDavid du Colombier cgen(l->left, &nod);
2873e12c5d1SDavid du Colombier regsalloc(&nod1, l->left);
2883e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
2893e12c5d1SDavid du Colombier regfree(&nod);
2903e12c5d1SDavid du Colombier
2913e12c5d1SDavid du Colombier nod = *n;
2923e12c5d1SDavid du Colombier nod.left = &nod2;
2933e12c5d1SDavid du Colombier nod2 = *l;
2943e12c5d1SDavid du Colombier nod2.left = &nod1;
2953e12c5d1SDavid du Colombier nod2.complex = 1;
2963e12c5d1SDavid du Colombier cgen(&nod, nn);
2973e12c5d1SDavid du Colombier
2983e12c5d1SDavid du Colombier return;
2993e12c5d1SDavid du Colombier }
3003e12c5d1SDavid du Colombier o = reg[REGARG];
3013e12c5d1SDavid du Colombier gargs(r, &nod, &nod1);
3023e12c5d1SDavid du Colombier if(l->addable < INDEXED) {
3033e12c5d1SDavid du Colombier reglcgen(&nod, l, Z);
3043e12c5d1SDavid du Colombier gopcode(OFUNC, Z, Z, &nod);
3053e12c5d1SDavid du Colombier regfree(&nod);
3063e12c5d1SDavid du Colombier } else
3073e12c5d1SDavid du Colombier gopcode(OFUNC, Z, Z, l);
3083e12c5d1SDavid du Colombier if(REGARG)
3093e12c5d1SDavid du Colombier if(o != reg[REGARG])
3103e12c5d1SDavid du Colombier reg[REGARG]--;
3113e12c5d1SDavid du Colombier if(nn != Z) {
3123e12c5d1SDavid du Colombier regret(&nod, n);
3133e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, nn);
3143e12c5d1SDavid du Colombier regfree(&nod);
3153e12c5d1SDavid du Colombier }
3163e12c5d1SDavid du Colombier break;
3173e12c5d1SDavid du Colombier
3183e12c5d1SDavid du Colombier case OIND:
3193e12c5d1SDavid du Colombier if(nn == Z) {
3203e12c5d1SDavid du Colombier cgen(l, nn);
3213e12c5d1SDavid du Colombier break;
3223e12c5d1SDavid du Colombier }
3233e12c5d1SDavid du Colombier regialloc(&nod, n, nn);
3243e12c5d1SDavid du Colombier r = l;
3253e12c5d1SDavid du Colombier while(r->op == OADD)
3263e12c5d1SDavid du Colombier r = r->right;
3273e12c5d1SDavid du Colombier if(sconst(r)) {
328219b2ee8SDavid du Colombier v = r->vconst;
329219b2ee8SDavid du Colombier r->vconst = 0;
3303e12c5d1SDavid du Colombier cgen(l, &nod);
331219b2ee8SDavid du Colombier nod.xoffset += v;
332219b2ee8SDavid du Colombier r->vconst = v;
3333e12c5d1SDavid du Colombier } else
3343e12c5d1SDavid du Colombier cgen(l, &nod);
3353e12c5d1SDavid du Colombier regind(&nod, n);
3363e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, nn);
3373e12c5d1SDavid du Colombier regfree(&nod);
3383e12c5d1SDavid du Colombier break;
3393e12c5d1SDavid du Colombier
3403e12c5d1SDavid du Colombier case OEQ:
3413e12c5d1SDavid du Colombier case ONE:
3423e12c5d1SDavid du Colombier case OLE:
3433e12c5d1SDavid du Colombier case OLT:
3443e12c5d1SDavid du Colombier case OGE:
3453e12c5d1SDavid du Colombier case OGT:
3463e12c5d1SDavid du Colombier case OLO:
3473e12c5d1SDavid du Colombier case OLS:
3483e12c5d1SDavid du Colombier case OHI:
3493e12c5d1SDavid du Colombier case OHS:
3503e12c5d1SDavid du Colombier if(nn == Z) {
3513e12c5d1SDavid du Colombier nullwarn(l, r);
3523e12c5d1SDavid du Colombier break;
3533e12c5d1SDavid du Colombier }
3543e12c5d1SDavid du Colombier boolgen(n, 1, nn);
3553e12c5d1SDavid du Colombier break;
3563e12c5d1SDavid du Colombier
3573e12c5d1SDavid du Colombier case OANDAND:
3583e12c5d1SDavid du Colombier case OOROR:
3593e12c5d1SDavid du Colombier boolgen(n, 1, nn);
3603e12c5d1SDavid du Colombier if(nn == Z)
3613e12c5d1SDavid du Colombier patch(p, pc);
3623e12c5d1SDavid du Colombier break;
3633e12c5d1SDavid du Colombier
3643e12c5d1SDavid du Colombier case ONOT:
3653e12c5d1SDavid du Colombier if(nn == Z) {
3663e12c5d1SDavid du Colombier nullwarn(l, Z);
3673e12c5d1SDavid du Colombier break;
3683e12c5d1SDavid du Colombier }
3693e12c5d1SDavid du Colombier boolgen(n, 1, nn);
3703e12c5d1SDavid du Colombier break;
3713e12c5d1SDavid du Colombier
3723e12c5d1SDavid du Colombier case OCOMMA:
3733e12c5d1SDavid du Colombier cgen(l, Z);
3743e12c5d1SDavid du Colombier cgen(r, nn);
3753e12c5d1SDavid du Colombier break;
3763e12c5d1SDavid du Colombier
3773e12c5d1SDavid du Colombier case OCAST:
3783e12c5d1SDavid du Colombier if(nn == Z) {
3793e12c5d1SDavid du Colombier nullwarn(l, Z);
3803e12c5d1SDavid du Colombier break;
3813e12c5d1SDavid du Colombier }
3823e12c5d1SDavid du Colombier /*
3833e12c5d1SDavid du Colombier * convert from types l->n->nn
3843e12c5d1SDavid du Colombier */
3853e12c5d1SDavid du Colombier if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
3863e12c5d1SDavid du Colombier /* both null, gen l->nn */
3873e12c5d1SDavid du Colombier cgen(l, nn);
3883e12c5d1SDavid du Colombier break;
3893e12c5d1SDavid du Colombier }
3903e12c5d1SDavid du Colombier regalloc(&nod, l, nn);
3913e12c5d1SDavid du Colombier cgen(l, &nod);
3923e12c5d1SDavid du Colombier regalloc(&nod1, n, &nod);
3933e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
3943e12c5d1SDavid du Colombier gopcode(OAS, &nod1, Z, nn);
3953e12c5d1SDavid du Colombier regfree(&nod1);
3963e12c5d1SDavid du Colombier regfree(&nod);
3973e12c5d1SDavid du Colombier break;
3983e12c5d1SDavid du Colombier
3993e12c5d1SDavid du Colombier case ODOT:
4003e12c5d1SDavid du Colombier sugen(l, nodrat, l->type->width);
4013e12c5d1SDavid du Colombier if(nn != Z) {
4023e12c5d1SDavid du Colombier warn(n, "non-interruptable temporary");
4033e12c5d1SDavid du Colombier nod = *nodrat;
4043e12c5d1SDavid du Colombier if(!r || r->op != OCONST) {
4053e12c5d1SDavid du Colombier diag(n, "DOT and no offset");
4063e12c5d1SDavid du Colombier break;
4073e12c5d1SDavid du Colombier }
408219b2ee8SDavid du Colombier nod.xoffset += (long)r->vconst;
4093e12c5d1SDavid du Colombier nod.type = n->type;
4103e12c5d1SDavid du Colombier cgen(&nod, nn);
4113e12c5d1SDavid du Colombier }
4123e12c5d1SDavid du Colombier break;
4133e12c5d1SDavid du Colombier
4143e12c5d1SDavid du Colombier case OCOND:
4153e12c5d1SDavid du Colombier bcgen(l, 1);
4163e12c5d1SDavid du Colombier p1 = p;
4173e12c5d1SDavid du Colombier cgen(r->left, nn);
4183e12c5d1SDavid du Colombier gbranch(OGOTO);
4193e12c5d1SDavid du Colombier patch(p1, pc);
4203e12c5d1SDavid du Colombier p1 = p;
4213e12c5d1SDavid du Colombier cgen(r->right, nn);
4223e12c5d1SDavid du Colombier patch(p1, pc);
4233e12c5d1SDavid du Colombier break;
4243e12c5d1SDavid du Colombier
4253e12c5d1SDavid du Colombier case OPOSTINC:
4263e12c5d1SDavid du Colombier case OPOSTDEC:
4273e12c5d1SDavid du Colombier v = 1;
4283e12c5d1SDavid du Colombier if(l->type->etype == TIND)
4293e12c5d1SDavid du Colombier v = l->type->link->width;
4303e12c5d1SDavid du Colombier if(o == OPOSTDEC)
4313e12c5d1SDavid du Colombier v = -v;
4323e12c5d1SDavid du Colombier if(l->op == OBIT)
4333e12c5d1SDavid du Colombier goto bitinc;
4343e12c5d1SDavid du Colombier if(nn == Z)
4353e12c5d1SDavid du Colombier goto pre;
4363e12c5d1SDavid du Colombier
4373e12c5d1SDavid du Colombier if(l->addable < INDEXED)
4383e12c5d1SDavid du Colombier reglcgen(&nod2, l, Z);
4393e12c5d1SDavid du Colombier else
4403e12c5d1SDavid du Colombier nod2 = *l;
4413e12c5d1SDavid du Colombier
4423e12c5d1SDavid du Colombier regalloc(&nod, l, nn);
4433e12c5d1SDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
4443e12c5d1SDavid du Colombier regalloc(&nod1, l, Z);
445219b2ee8SDavid du Colombier if(typefd[l->type->etype]) {
4463e12c5d1SDavid du Colombier regalloc(&nod3, l, Z);
4473e12c5d1SDavid du Colombier if(v < 0) {
4483e12c5d1SDavid du Colombier gopcode(OAS, nodfconst(-v), Z, &nod3);
4493e12c5d1SDavid du Colombier gopcode(OSUB, &nod3, &nod, &nod1);
4503e12c5d1SDavid du Colombier } else {
4513e12c5d1SDavid du Colombier gopcode(OAS, nodfconst(v), Z, &nod3);
4523e12c5d1SDavid du Colombier gopcode(OADD, &nod3, &nod, &nod1);
4533e12c5d1SDavid du Colombier }
4543e12c5d1SDavid du Colombier regfree(&nod3);
4553e12c5d1SDavid du Colombier } else
4563e12c5d1SDavid du Colombier gopcode(OADD, nodconst(v), &nod, &nod1);
4573e12c5d1SDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
4583e12c5d1SDavid du Colombier
4593e12c5d1SDavid du Colombier regfree(&nod);
4603e12c5d1SDavid du Colombier regfree(&nod1);
4613e12c5d1SDavid du Colombier if(l->addable < INDEXED)
4623e12c5d1SDavid du Colombier regfree(&nod2);
4633e12c5d1SDavid du Colombier break;
4643e12c5d1SDavid du Colombier
4653e12c5d1SDavid du Colombier case OPREINC:
4663e12c5d1SDavid du Colombier case OPREDEC:
4673e12c5d1SDavid du Colombier v = 1;
4683e12c5d1SDavid du Colombier if(l->type->etype == TIND)
4693e12c5d1SDavid du Colombier v = l->type->link->width;
4703e12c5d1SDavid du Colombier if(o == OPREDEC)
4713e12c5d1SDavid du Colombier v = -v;
4723e12c5d1SDavid du Colombier if(l->op == OBIT)
4733e12c5d1SDavid du Colombier goto bitinc;
4743e12c5d1SDavid du Colombier
4753e12c5d1SDavid du Colombier pre:
4763e12c5d1SDavid du Colombier if(l->addable < INDEXED)
4773e12c5d1SDavid du Colombier reglcgen(&nod2, l, Z);
4783e12c5d1SDavid du Colombier else
4793e12c5d1SDavid du Colombier nod2 = *l;
4803e12c5d1SDavid du Colombier
4813e12c5d1SDavid du Colombier regalloc(&nod, l, nn);
4823e12c5d1SDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
483219b2ee8SDavid du Colombier if(typefd[l->type->etype]) {
4843e12c5d1SDavid du Colombier regalloc(&nod3, l, Z);
4853e12c5d1SDavid du Colombier if(v < 0) {
4863e12c5d1SDavid du Colombier gopcode(OAS, nodfconst(-v), Z, &nod3);
4873e12c5d1SDavid du Colombier gopcode(OSUB, &nod3, Z, &nod);
4883e12c5d1SDavid du Colombier } else {
4893e12c5d1SDavid du Colombier gopcode(OAS, nodfconst(v), Z, &nod3);
4903e12c5d1SDavid du Colombier gopcode(OADD, &nod3, Z, &nod);
4913e12c5d1SDavid du Colombier }
4923e12c5d1SDavid du Colombier regfree(&nod3);
4933e12c5d1SDavid du Colombier } else
4943e12c5d1SDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
4953e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod2);
496*4ac975e2SDavid du Colombier if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
497*4ac975e2SDavid du Colombier gins(ANOP, l, Z);
4983e12c5d1SDavid du Colombier
4993e12c5d1SDavid du Colombier regfree(&nod);
5003e12c5d1SDavid du Colombier if(l->addable < INDEXED)
5013e12c5d1SDavid du Colombier regfree(&nod2);
5023e12c5d1SDavid du Colombier break;
5033e12c5d1SDavid du Colombier
5043e12c5d1SDavid du Colombier bitinc:
5053e12c5d1SDavid du Colombier if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
5063e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, Z);
5073e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, nn);
5083e12c5d1SDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
5093e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, Z);
5103e12c5d1SDavid du Colombier break;
5113e12c5d1SDavid du Colombier }
5123e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, nn);
5133e12c5d1SDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
5143e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
5153e12c5d1SDavid du Colombier break;
5163e12c5d1SDavid du Colombier }
5173e12c5d1SDavid du Colombier cursafe = curs;
5183e12c5d1SDavid du Colombier }
5193e12c5d1SDavid du Colombier
5203e12c5d1SDavid du Colombier void
reglcgen(Node * t,Node * n,Node * nn)5213e12c5d1SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
5223e12c5d1SDavid du Colombier {
5233e12c5d1SDavid du Colombier Node *r;
5243e12c5d1SDavid du Colombier long v;
5253e12c5d1SDavid du Colombier
5263e12c5d1SDavid du Colombier regialloc(t, n, nn);
5273e12c5d1SDavid du Colombier if(n->op == OIND) {
5283e12c5d1SDavid du Colombier r = n->left;
5293e12c5d1SDavid du Colombier while(r->op == OADD)
5303e12c5d1SDavid du Colombier r = r->right;
5313e12c5d1SDavid du Colombier if(sconst(r)) {
532219b2ee8SDavid du Colombier v = r->vconst;
533219b2ee8SDavid du Colombier r->vconst = 0;
5343e12c5d1SDavid du Colombier lcgen(n, t);
535219b2ee8SDavid du Colombier t->xoffset += v;
536219b2ee8SDavid du Colombier r->vconst = v;
5373e12c5d1SDavid du Colombier regind(t, n);
5383e12c5d1SDavid du Colombier return;
5393e12c5d1SDavid du Colombier }
5403e12c5d1SDavid du Colombier }
5413e12c5d1SDavid du Colombier lcgen(n, t);
5423e12c5d1SDavid du Colombier regind(t, n);
5433e12c5d1SDavid du Colombier }
5443e12c5d1SDavid du Colombier
5453e12c5d1SDavid du Colombier void
lcgen(Node * n,Node * nn)5463e12c5d1SDavid du Colombier lcgen(Node *n, Node *nn)
5473e12c5d1SDavid du Colombier {
5483e12c5d1SDavid du Colombier Prog *p1;
5493e12c5d1SDavid du Colombier Node nod;
5503e12c5d1SDavid du Colombier
5513e12c5d1SDavid du Colombier if(debug['g']) {
5523e12c5d1SDavid du Colombier prtree(nn, "lcgen lhs");
5533e12c5d1SDavid du Colombier prtree(n, "lcgen");
5543e12c5d1SDavid du Colombier }
5553e12c5d1SDavid du Colombier if(n == Z || n->type == T)
5563e12c5d1SDavid du Colombier return;
5573e12c5d1SDavid du Colombier if(nn == Z) {
5583e12c5d1SDavid du Colombier nn = &nod;
5593e12c5d1SDavid du Colombier regalloc(&nod, n, Z);
5603e12c5d1SDavid du Colombier }
5613e12c5d1SDavid du Colombier switch(n->op) {
5623e12c5d1SDavid du Colombier default:
5633e12c5d1SDavid du Colombier if(n->addable < INDEXED) {
5643e12c5d1SDavid du Colombier diag(n, "unknown op in lcgen: %O", n->op);
5653e12c5d1SDavid du Colombier break;
5663e12c5d1SDavid du Colombier }
5673e12c5d1SDavid du Colombier nod = *n;
5683e12c5d1SDavid du Colombier nod.op = OADDR;
5693e12c5d1SDavid du Colombier nod.left = n;
5703e12c5d1SDavid du Colombier nod.right = Z;
5713e12c5d1SDavid du Colombier nod.type = types[TIND];
5723e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, nn);
5733e12c5d1SDavid du Colombier break;
5743e12c5d1SDavid du Colombier
5753e12c5d1SDavid du Colombier case OCOMMA:
5763e12c5d1SDavid du Colombier cgen(n->left, n->left);
5773e12c5d1SDavid du Colombier lcgen(n->right, nn);
5783e12c5d1SDavid du Colombier break;
5793e12c5d1SDavid du Colombier
5803e12c5d1SDavid du Colombier case OIND:
5813e12c5d1SDavid du Colombier cgen(n->left, nn);
5823e12c5d1SDavid du Colombier break;
5833e12c5d1SDavid du Colombier
5843e12c5d1SDavid du Colombier case OCOND:
5853e12c5d1SDavid du Colombier bcgen(n->left, 1);
5863e12c5d1SDavid du Colombier p1 = p;
5873e12c5d1SDavid du Colombier lcgen(n->right->left, nn);
5883e12c5d1SDavid du Colombier gbranch(OGOTO);
5893e12c5d1SDavid du Colombier patch(p1, pc);
5903e12c5d1SDavid du Colombier p1 = p;
5913e12c5d1SDavid du Colombier lcgen(n->right->right, nn);
5923e12c5d1SDavid du Colombier patch(p1, pc);
5933e12c5d1SDavid du Colombier break;
5943e12c5d1SDavid du Colombier }
5953e12c5d1SDavid du Colombier }
5963e12c5d1SDavid du Colombier
5973e12c5d1SDavid du Colombier void
bcgen(Node * n,int true)5983e12c5d1SDavid du Colombier bcgen(Node *n, int true)
5993e12c5d1SDavid du Colombier {
6003e12c5d1SDavid du Colombier
6013e12c5d1SDavid du Colombier if(n->type == T)
6023e12c5d1SDavid du Colombier gbranch(OGOTO);
6033e12c5d1SDavid du Colombier else
6043e12c5d1SDavid du Colombier boolgen(n, true, Z);
6053e12c5d1SDavid du Colombier }
6063e12c5d1SDavid du Colombier
6073e12c5d1SDavid du Colombier void
boolgen(Node * n,int true,Node * nn)6083e12c5d1SDavid du Colombier boolgen(Node *n, int true, Node *nn)
6093e12c5d1SDavid du Colombier {
6103e12c5d1SDavid du Colombier int o;
6113e12c5d1SDavid du Colombier Prog *p1, *p2;
6123e12c5d1SDavid du Colombier Node *l, *r, nod, nod1;
6133e12c5d1SDavid du Colombier long curs;
6143e12c5d1SDavid du Colombier
6153e12c5d1SDavid du Colombier if(debug['g']) {
6163e12c5d1SDavid du Colombier prtree(nn, "boolgen lhs");
6173e12c5d1SDavid du Colombier prtree(n, "boolgen");
6183e12c5d1SDavid du Colombier }
6193e12c5d1SDavid du Colombier curs = cursafe;
6203e12c5d1SDavid du Colombier l = n->left;
6213e12c5d1SDavid du Colombier r = n->right;
6223e12c5d1SDavid du Colombier switch(n->op) {
6233e12c5d1SDavid du Colombier
6243e12c5d1SDavid du Colombier default:
6253e12c5d1SDavid du Colombier if(n->op == OCONST) {
6263e12c5d1SDavid du Colombier o = vconst(n);
6273e12c5d1SDavid du Colombier if(!true)
6283e12c5d1SDavid du Colombier o = !o;
6293e12c5d1SDavid du Colombier gbranch(OGOTO);
6303e12c5d1SDavid du Colombier if(o) {
6313e12c5d1SDavid du Colombier p1 = p;
6323e12c5d1SDavid du Colombier gbranch(OGOTO);
6333e12c5d1SDavid du Colombier patch(p1, pc);
6343e12c5d1SDavid du Colombier }
6353e12c5d1SDavid du Colombier goto com;
6363e12c5d1SDavid du Colombier }
6373e12c5d1SDavid du Colombier regalloc(&nod, n, nn);
6383e12c5d1SDavid du Colombier cgen(n, &nod);
6393e12c5d1SDavid du Colombier o = ONE;
6403e12c5d1SDavid du Colombier if(true)
6413e12c5d1SDavid du Colombier o = comrel[relindex(o)];
642219b2ee8SDavid du Colombier if(typefd[n->type->etype]) {
6433e12c5d1SDavid du Colombier nodreg(&nod1, n, NREG+FREGZERO);
6443e12c5d1SDavid du Colombier gopcode(o, &nod, Z, &nod1);
6453e12c5d1SDavid du Colombier } else
6463e12c5d1SDavid du Colombier gopcode(o, &nod, Z, nodconst(0));
6473e12c5d1SDavid du Colombier regfree(&nod);
6483e12c5d1SDavid du Colombier goto com;
6493e12c5d1SDavid du Colombier
6503e12c5d1SDavid du Colombier case OCOMMA:
6513e12c5d1SDavid du Colombier cgen(l, Z);
6523e12c5d1SDavid du Colombier boolgen(r, true, nn);
6533e12c5d1SDavid du Colombier break;
6543e12c5d1SDavid du Colombier
6553e12c5d1SDavid du Colombier case ONOT:
6563e12c5d1SDavid du Colombier boolgen(l, !true, nn);
6573e12c5d1SDavid du Colombier break;
6583e12c5d1SDavid du Colombier
6593e12c5d1SDavid du Colombier case OCOND:
6603e12c5d1SDavid du Colombier bcgen(l, 1);
6613e12c5d1SDavid du Colombier p1 = p;
6623e12c5d1SDavid du Colombier bcgen(r->left, true);
6633e12c5d1SDavid du Colombier p2 = p;
6643e12c5d1SDavid du Colombier gbranch(OGOTO);
6653e12c5d1SDavid du Colombier patch(p1, pc);
6663e12c5d1SDavid du Colombier p1 = p;
6673e12c5d1SDavid du Colombier bcgen(r->right, !true);
6683e12c5d1SDavid du Colombier patch(p2, pc);
6693e12c5d1SDavid du Colombier p2 = p;
6703e12c5d1SDavid du Colombier gbranch(OGOTO);
6713e12c5d1SDavid du Colombier patch(p1, pc);
6723e12c5d1SDavid du Colombier patch(p2, pc);
6733e12c5d1SDavid du Colombier goto com;
6743e12c5d1SDavid du Colombier
6753e12c5d1SDavid du Colombier case OANDAND:
6763e12c5d1SDavid du Colombier if(!true)
6773e12c5d1SDavid du Colombier goto caseor;
6783e12c5d1SDavid du Colombier
6793e12c5d1SDavid du Colombier caseand:
6803e12c5d1SDavid du Colombier bcgen(l, true);
6813e12c5d1SDavid du Colombier p1 = p;
6823e12c5d1SDavid du Colombier bcgen(r, !true);
6833e12c5d1SDavid du Colombier p2 = p;
6843e12c5d1SDavid du Colombier patch(p1, pc);
6853e12c5d1SDavid du Colombier gbranch(OGOTO);
6863e12c5d1SDavid du Colombier patch(p2, pc);
6873e12c5d1SDavid du Colombier goto com;
6883e12c5d1SDavid du Colombier
6893e12c5d1SDavid du Colombier case OOROR:
6903e12c5d1SDavid du Colombier if(!true)
6913e12c5d1SDavid du Colombier goto caseand;
6923e12c5d1SDavid du Colombier
6933e12c5d1SDavid du Colombier caseor:
6943e12c5d1SDavid du Colombier bcgen(l, !true);
6953e12c5d1SDavid du Colombier p1 = p;
6963e12c5d1SDavid du Colombier bcgen(r, !true);
6973e12c5d1SDavid du Colombier p2 = p;
6983e12c5d1SDavid du Colombier gbranch(OGOTO);
6993e12c5d1SDavid du Colombier patch(p1, pc);
7003e12c5d1SDavid du Colombier patch(p2, pc);
7013e12c5d1SDavid du Colombier goto com;
7023e12c5d1SDavid du Colombier
7033e12c5d1SDavid du Colombier case OEQ:
7043e12c5d1SDavid du Colombier case ONE:
7053e12c5d1SDavid du Colombier case OLE:
7063e12c5d1SDavid du Colombier case OLT:
7073e12c5d1SDavid du Colombier case OGE:
7083e12c5d1SDavid du Colombier case OGT:
7093e12c5d1SDavid du Colombier case OHI:
7103e12c5d1SDavid du Colombier case OHS:
7113e12c5d1SDavid du Colombier case OLO:
7123e12c5d1SDavid du Colombier case OLS:
7133e12c5d1SDavid du Colombier o = n->op;
7143e12c5d1SDavid du Colombier if(true)
7153e12c5d1SDavid du Colombier o = comrel[relindex(o)];
7163e12c5d1SDavid du Colombier if(l->complex >= FNX && r->complex >= FNX) {
7173e12c5d1SDavid du Colombier regret(&nod, r);
7183e12c5d1SDavid du Colombier cgen(r, &nod);
7193e12c5d1SDavid du Colombier regsalloc(&nod1, r);
7203e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
7213e12c5d1SDavid du Colombier regfree(&nod);
7223e12c5d1SDavid du Colombier nod = *n;
7233e12c5d1SDavid du Colombier nod.right = &nod1;
7243e12c5d1SDavid du Colombier boolgen(&nod, true, nn);
7253e12c5d1SDavid du Colombier break;
7263e12c5d1SDavid du Colombier }
7273e12c5d1SDavid du Colombier if(sconst(r)) {
7283e12c5d1SDavid du Colombier regalloc(&nod, l, nn);
7293e12c5d1SDavid du Colombier cgen(l, &nod);
7303e12c5d1SDavid du Colombier gopcode(o, &nod, Z, r);
7313e12c5d1SDavid du Colombier regfree(&nod);
7323e12c5d1SDavid du Colombier goto com;
7333e12c5d1SDavid du Colombier }
7343e12c5d1SDavid du Colombier if(l->complex >= r->complex) {
7353e12c5d1SDavid du Colombier regalloc(&nod1, l, nn);
7363e12c5d1SDavid du Colombier cgen(l, &nod1);
7373e12c5d1SDavid du Colombier regalloc(&nod, r, Z);
7383e12c5d1SDavid du Colombier cgen(r, &nod);
7393e12c5d1SDavid du Colombier } else {
7403e12c5d1SDavid du Colombier regalloc(&nod, r, nn);
7413e12c5d1SDavid du Colombier cgen(r, &nod);
7423e12c5d1SDavid du Colombier regalloc(&nod1, l, Z);
7433e12c5d1SDavid du Colombier cgen(l, &nod1);
7443e12c5d1SDavid du Colombier }
7453e12c5d1SDavid du Colombier gopcode(o, &nod1, Z, &nod);
7463e12c5d1SDavid du Colombier regfree(&nod);
7473e12c5d1SDavid du Colombier regfree(&nod1);
7483e12c5d1SDavid du Colombier
7493e12c5d1SDavid du Colombier com:
7503e12c5d1SDavid du Colombier if(nn != Z) {
7513e12c5d1SDavid du Colombier p1 = p;
7523e12c5d1SDavid du Colombier gopcode(OAS, nodconst(1L), Z, nn);
7533e12c5d1SDavid du Colombier gbranch(OGOTO);
7543e12c5d1SDavid du Colombier p2 = p;
7553e12c5d1SDavid du Colombier patch(p1, pc);
7563e12c5d1SDavid du Colombier gopcode(OAS, nodconst(0L), Z, nn);
7573e12c5d1SDavid du Colombier patch(p2, pc);
7583e12c5d1SDavid du Colombier }
7593e12c5d1SDavid du Colombier break;
7603e12c5d1SDavid du Colombier }
7613e12c5d1SDavid du Colombier cursafe = curs;
7623e12c5d1SDavid du Colombier }
7633e12c5d1SDavid du Colombier
7643e12c5d1SDavid du Colombier void
sugen(Node * n,Node * nn,long w)7653e12c5d1SDavid du Colombier sugen(Node *n, Node *nn, long w)
7663e12c5d1SDavid du Colombier {
7673e12c5d1SDavid du Colombier Prog *p1;
7683e12c5d1SDavid du Colombier Node nod0, nod1, nod2, nod3, nod4, *l, *r;
7693e12c5d1SDavid du Colombier Type *t;
7703e12c5d1SDavid du Colombier long pc1;
7713e12c5d1SDavid du Colombier int i, m, c;
7723e12c5d1SDavid du Colombier
7733e12c5d1SDavid du Colombier if(n == Z || n->type == T)
7743e12c5d1SDavid du Colombier return;
7753e12c5d1SDavid du Colombier if(debug['g']) {
7763e12c5d1SDavid du Colombier prtree(nn, "sugen lhs");
7773e12c5d1SDavid du Colombier prtree(n, "sugen");
7783e12c5d1SDavid du Colombier }
7793e12c5d1SDavid du Colombier if(nn == nodrat)
7803e12c5d1SDavid du Colombier if(w > nrathole)
7813e12c5d1SDavid du Colombier nrathole = w;
7823e12c5d1SDavid du Colombier switch(n->op) {
7833e12c5d1SDavid du Colombier case OIND:
7843e12c5d1SDavid du Colombier if(nn == Z) {
7853e12c5d1SDavid du Colombier nullwarn(n->left, Z);
7863e12c5d1SDavid du Colombier break;
7873e12c5d1SDavid du Colombier }
7883e12c5d1SDavid du Colombier
7893e12c5d1SDavid du Colombier default:
7903e12c5d1SDavid du Colombier goto copy;
7913e12c5d1SDavid du Colombier
792219b2ee8SDavid du Colombier case OCONST:
793219b2ee8SDavid du Colombier if(n->type && typev[n->type->etype]) {
794219b2ee8SDavid du Colombier if(nn == Z) {
795219b2ee8SDavid du Colombier nullwarn(n->left, Z);
796219b2ee8SDavid du Colombier break;
797219b2ee8SDavid du Colombier }
798219b2ee8SDavid du Colombier
799219b2ee8SDavid du Colombier t = nn->type;
800219b2ee8SDavid du Colombier nn->type = types[TLONG];
801219b2ee8SDavid du Colombier reglcgen(&nod1, nn, Z);
802219b2ee8SDavid du Colombier nn->type = t;
803219b2ee8SDavid du Colombier
80480ee5cbfSDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
805219b2ee8SDavid du Colombier gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
80680ee5cbfSDavid du Colombier else
807219b2ee8SDavid du Colombier gopcode(OAS, nod32const(n->vconst), Z, &nod1);
80880ee5cbfSDavid du Colombier nod1.xoffset += SZ_LONG;
80980ee5cbfSDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
81080ee5cbfSDavid du Colombier gopcode(OAS, nod32const(n->vconst), Z, &nod1);
81180ee5cbfSDavid du Colombier else
81280ee5cbfSDavid du Colombier gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
813219b2ee8SDavid du Colombier
814219b2ee8SDavid du Colombier regfree(&nod1);
815219b2ee8SDavid du Colombier break;
816219b2ee8SDavid du Colombier }
817219b2ee8SDavid du Colombier goto copy;
818219b2ee8SDavid du Colombier
8193e12c5d1SDavid du Colombier case ODOT:
8203e12c5d1SDavid du Colombier l = n->left;
8213e12c5d1SDavid du Colombier sugen(l, nodrat, l->type->width);
8223e12c5d1SDavid du Colombier if(nn != Z) {
8233e12c5d1SDavid du Colombier warn(n, "non-interruptable temporary");
8243e12c5d1SDavid du Colombier nod1 = *nodrat;
8253e12c5d1SDavid du Colombier r = n->right;
8263e12c5d1SDavid du Colombier if(!r || r->op != OCONST) {
8273e12c5d1SDavid du Colombier diag(n, "DOT and no offset");
8283e12c5d1SDavid du Colombier break;
8293e12c5d1SDavid du Colombier }
830219b2ee8SDavid du Colombier nod1.xoffset += (long)r->vconst;
8313e12c5d1SDavid du Colombier nod1.type = n->type;
8323e12c5d1SDavid du Colombier sugen(&nod1, nn, w);
8333e12c5d1SDavid du Colombier }
8343e12c5d1SDavid du Colombier break;
8353e12c5d1SDavid du Colombier
8363e12c5d1SDavid du Colombier case OSTRUCT:
837219b2ee8SDavid du Colombier /*
838219b2ee8SDavid du Colombier * rewrite so lhs has no fn call
839219b2ee8SDavid du Colombier */
840219b2ee8SDavid du Colombier if(nn != Z && nn->complex >= FNX) {
841219b2ee8SDavid du Colombier nod1 = *n;
842219b2ee8SDavid du Colombier nod1.type = typ(TIND, n->type);
843219b2ee8SDavid du Colombier regret(&nod2, &nod1);
844219b2ee8SDavid du Colombier lcgen(nn, &nod2);
845219b2ee8SDavid du Colombier regsalloc(&nod0, &nod1);
846219b2ee8SDavid du Colombier gopcode(OAS, &nod2, Z, &nod0);
847219b2ee8SDavid du Colombier regfree(&nod2);
848219b2ee8SDavid du Colombier
849219b2ee8SDavid du Colombier nod1 = *n;
850219b2ee8SDavid du Colombier nod1.op = OIND;
851219b2ee8SDavid du Colombier nod1.left = &nod0;
852219b2ee8SDavid du Colombier nod1.right = Z;
853219b2ee8SDavid du Colombier nod1.complex = 1;
854219b2ee8SDavid du Colombier
855219b2ee8SDavid du Colombier sugen(n, &nod1, w);
856219b2ee8SDavid du Colombier return;
857219b2ee8SDavid du Colombier }
858219b2ee8SDavid du Colombier
8593e12c5d1SDavid du Colombier r = n->left;
8603e12c5d1SDavid du Colombier for(t = n->type->link; t != T; t = t->down) {
8613e12c5d1SDavid du Colombier l = r;
8623e12c5d1SDavid du Colombier if(r->op == OLIST) {
8633e12c5d1SDavid du Colombier l = r->left;
8643e12c5d1SDavid du Colombier r = r->right;
8653e12c5d1SDavid du Colombier }
8663e12c5d1SDavid du Colombier if(nn == Z) {
8673e12c5d1SDavid du Colombier cgen(l, nn);
8683e12c5d1SDavid du Colombier continue;
8693e12c5d1SDavid du Colombier }
8703e12c5d1SDavid du Colombier /*
8713e12c5d1SDavid du Colombier * hand craft *(&nn + o) = l
8723e12c5d1SDavid du Colombier */
8733e12c5d1SDavid du Colombier nod0 = znode;
8743e12c5d1SDavid du Colombier nod0.op = OAS;
8753e12c5d1SDavid du Colombier nod0.type = t;
8763e12c5d1SDavid du Colombier nod0.left = &nod1;
8773e12c5d1SDavid du Colombier nod0.right = l;
8783e12c5d1SDavid du Colombier
8793e12c5d1SDavid du Colombier nod1 = znode;
8803e12c5d1SDavid du Colombier nod1.op = OIND;
8813e12c5d1SDavid du Colombier nod1.type = t;
8823e12c5d1SDavid du Colombier nod1.left = &nod2;
8833e12c5d1SDavid du Colombier
8843e12c5d1SDavid du Colombier nod2 = znode;
8853e12c5d1SDavid du Colombier nod2.op = OADD;
8863e12c5d1SDavid du Colombier nod2.type = typ(TIND, t);
8873e12c5d1SDavid du Colombier nod2.left = &nod3;
8883e12c5d1SDavid du Colombier nod2.right = &nod4;
8893e12c5d1SDavid du Colombier
8903e12c5d1SDavid du Colombier nod3 = znode;
8913e12c5d1SDavid du Colombier nod3.op = OADDR;
8923e12c5d1SDavid du Colombier nod3.type = nod2.type;
8933e12c5d1SDavid du Colombier nod3.left = nn;
8943e12c5d1SDavid du Colombier
8953e12c5d1SDavid du Colombier nod4 = znode;
8963e12c5d1SDavid du Colombier nod4.op = OCONST;
8973e12c5d1SDavid du Colombier nod4.type = nod2.type;
8987dd7cddfSDavid du Colombier nod4.vconst = t->offset;
8993e12c5d1SDavid du Colombier
9003e12c5d1SDavid du Colombier ccom(&nod0);
9013e12c5d1SDavid du Colombier acom(&nod0);
9023e12c5d1SDavid du Colombier xcom(&nod0);
9033e12c5d1SDavid du Colombier nod0.addable = 0;
9043e12c5d1SDavid du Colombier
9053e12c5d1SDavid du Colombier cgen(&nod0, Z);
9063e12c5d1SDavid du Colombier }
9073e12c5d1SDavid du Colombier break;
9083e12c5d1SDavid du Colombier
9093e12c5d1SDavid du Colombier case OAS:
9103e12c5d1SDavid du Colombier if(nn == Z) {
9113e12c5d1SDavid du Colombier if(n->addable < INDEXED)
9123e12c5d1SDavid du Colombier sugen(n->right, n->left, w);
9133e12c5d1SDavid du Colombier break;
9143e12c5d1SDavid du Colombier }
9153e12c5d1SDavid du Colombier /* BOTCH -- functions can clobber rathole */
9163e12c5d1SDavid du Colombier sugen(n->right, nodrat, w);
9173e12c5d1SDavid du Colombier warn(n, "non-interruptable temporary");
9183e12c5d1SDavid du Colombier sugen(nodrat, n->left, w);
9193e12c5d1SDavid du Colombier sugen(nodrat, nn, w);
9203e12c5d1SDavid du Colombier break;
9213e12c5d1SDavid du Colombier
9223e12c5d1SDavid du Colombier case OFUNC:
9233e12c5d1SDavid du Colombier if(nn == Z) {
9243e12c5d1SDavid du Colombier sugen(n, nodrat, w);
9253e12c5d1SDavid du Colombier break;
9263e12c5d1SDavid du Colombier }
9273e12c5d1SDavid du Colombier if(nn->op != OIND) {
9283e12c5d1SDavid du Colombier nn = new1(OADDR, nn, Z);
9293e12c5d1SDavid du Colombier nn->type = types[TIND];
9303e12c5d1SDavid du Colombier nn->addable = 0;
9313e12c5d1SDavid du Colombier } else
9323e12c5d1SDavid du Colombier nn = nn->left;
9333e12c5d1SDavid du Colombier n = new(OFUNC, n->left, new(OLIST, nn, n->right));
9343e12c5d1SDavid du Colombier n->type = types[TVOID];
9353e12c5d1SDavid du Colombier n->left->type = types[TVOID];
9363e12c5d1SDavid du Colombier cgen(n, Z);
9373e12c5d1SDavid du Colombier break;
9383e12c5d1SDavid du Colombier
9393e12c5d1SDavid du Colombier case OCOND:
9403e12c5d1SDavid du Colombier bcgen(n->left, 1);
9413e12c5d1SDavid du Colombier p1 = p;
9423e12c5d1SDavid du Colombier sugen(n->right->left, nn, w);
9433e12c5d1SDavid du Colombier gbranch(OGOTO);
9443e12c5d1SDavid du Colombier patch(p1, pc);
9453e12c5d1SDavid du Colombier p1 = p;
9463e12c5d1SDavid du Colombier sugen(n->right->right, nn, w);
9473e12c5d1SDavid du Colombier patch(p1, pc);
9483e12c5d1SDavid du Colombier break;
9493e12c5d1SDavid du Colombier
9503e12c5d1SDavid du Colombier case OCOMMA:
9513e12c5d1SDavid du Colombier cgen(n->left, Z);
9523e12c5d1SDavid du Colombier sugen(n->right, nn, w);
9533e12c5d1SDavid du Colombier break;
9543e12c5d1SDavid du Colombier }
9553e12c5d1SDavid du Colombier return;
9563e12c5d1SDavid du Colombier
9573e12c5d1SDavid du Colombier copy:
9583e12c5d1SDavid du Colombier if(nn == Z)
9593e12c5d1SDavid du Colombier return;
9603e12c5d1SDavid du Colombier if(n->complex >= FNX && nn->complex >= FNX) {
961219b2ee8SDavid du Colombier t = nn->type;
962219b2ee8SDavid du Colombier nn->type = types[TLONG];
963219b2ee8SDavid du Colombier regialloc(&nod1, nn, Z);
964219b2ee8SDavid du Colombier lcgen(nn, &nod1);
965219b2ee8SDavid du Colombier regsalloc(&nod2, nn);
966219b2ee8SDavid du Colombier nn->type = t;
967219b2ee8SDavid du Colombier
968219b2ee8SDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
969219b2ee8SDavid du Colombier regfree(&nod1);
970219b2ee8SDavid du Colombier
971219b2ee8SDavid du Colombier nod2.type = typ(TIND, t);
972219b2ee8SDavid du Colombier
973219b2ee8SDavid du Colombier nod1 = nod2;
974219b2ee8SDavid du Colombier nod1.op = OIND;
975219b2ee8SDavid du Colombier nod1.left = &nod2;
976219b2ee8SDavid du Colombier nod1.right = Z;
977219b2ee8SDavid du Colombier nod1.complex = 1;
978219b2ee8SDavid du Colombier nod1.type = t;
979219b2ee8SDavid du Colombier
980219b2ee8SDavid du Colombier sugen(n, &nod1, w);
9813e12c5d1SDavid du Colombier return;
9823e12c5d1SDavid du Colombier }
9833e12c5d1SDavid du Colombier
9843e12c5d1SDavid du Colombier if(n->complex > nn->complex) {
9853e12c5d1SDavid du Colombier t = n->type;
9863e12c5d1SDavid du Colombier n->type = types[TLONG];
9873e12c5d1SDavid du Colombier reglcgen(&nod1, n, Z);
9883e12c5d1SDavid du Colombier n->type = t;
9893e12c5d1SDavid du Colombier
9903e12c5d1SDavid du Colombier t = nn->type;
9913e12c5d1SDavid du Colombier nn->type = types[TLONG];
9923e12c5d1SDavid du Colombier reglcgen(&nod2, nn, Z);
9933e12c5d1SDavid du Colombier nn->type = t;
9943e12c5d1SDavid du Colombier } else {
9953e12c5d1SDavid du Colombier t = nn->type;
9963e12c5d1SDavid du Colombier nn->type = types[TLONG];
9973e12c5d1SDavid du Colombier reglcgen(&nod2, nn, Z);
9983e12c5d1SDavid du Colombier nn->type = t;
9993e12c5d1SDavid du Colombier
10003e12c5d1SDavid du Colombier t = n->type;
10013e12c5d1SDavid du Colombier n->type = types[TLONG];
10023e12c5d1SDavid du Colombier reglcgen(&nod1, n, Z);
10033e12c5d1SDavid du Colombier n->type = t;
10043e12c5d1SDavid du Colombier }
10053e12c5d1SDavid du Colombier
10063e12c5d1SDavid du Colombier w /= SZ_LONG;
10073e12c5d1SDavid du Colombier if(w <= 5) {
10083e12c5d1SDavid du Colombier layout(&nod1, &nod2, w, 0, Z);
10093e12c5d1SDavid du Colombier goto out;
10103e12c5d1SDavid du Colombier }
10113e12c5d1SDavid du Colombier
10123e12c5d1SDavid du Colombier /*
10133e12c5d1SDavid du Colombier * minimize space for unrolling loop
10143e12c5d1SDavid du Colombier * 3,4,5 times. (6 or more is never minimum)
10153e12c5d1SDavid du Colombier * if small structure, try 2 also.
10163e12c5d1SDavid du Colombier */
10173e12c5d1SDavid du Colombier c = 0; /* set */
10183e12c5d1SDavid du Colombier m = 100;
10193e12c5d1SDavid du Colombier i = 3;
10203e12c5d1SDavid du Colombier if(w <= 15)
10213e12c5d1SDavid du Colombier i = 2;
10223e12c5d1SDavid du Colombier for(; i<=5; i++)
10233e12c5d1SDavid du Colombier if(i + w%i <= m) {
10243e12c5d1SDavid du Colombier c = i;
10253e12c5d1SDavid du Colombier m = c + w%c;
10263e12c5d1SDavid du Colombier }
10273e12c5d1SDavid du Colombier
10283e12c5d1SDavid du Colombier regalloc(&nod3, ®node, Z);
10293e12c5d1SDavid du Colombier layout(&nod1, &nod2, w%c, w/c, &nod3);
10303e12c5d1SDavid du Colombier
10313e12c5d1SDavid du Colombier pc1 = pc;
10323e12c5d1SDavid du Colombier layout(&nod1, &nod2, c, 0, Z);
10333e12c5d1SDavid du Colombier
10343e12c5d1SDavid du Colombier gopcode(OSUB, nodconst(1L), Z, &nod3);
10353e12c5d1SDavid du Colombier nod1.op = OREGISTER;
10363e12c5d1SDavid du Colombier gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
10373e12c5d1SDavid du Colombier nod2.op = OREGISTER;
10383e12c5d1SDavid du Colombier gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
10393e12c5d1SDavid du Colombier
10403e12c5d1SDavid du Colombier gopcode(OGT, &nod3, Z, nodconst(0));
10413e12c5d1SDavid du Colombier patch(p, pc1);
10423e12c5d1SDavid du Colombier
10433e12c5d1SDavid du Colombier regfree(&nod3);
10443e12c5d1SDavid du Colombier out:
10453e12c5d1SDavid du Colombier regfree(&nod1);
10463e12c5d1SDavid du Colombier regfree(&nod2);
10473e12c5d1SDavid du Colombier }
10483e12c5d1SDavid du Colombier
10493e12c5d1SDavid du Colombier void
layout(Node * f,Node * t,int c,int cv,Node * cn)10503e12c5d1SDavid du Colombier layout(Node *f, Node *t, int c, int cv, Node *cn)
10513e12c5d1SDavid du Colombier {
10523e12c5d1SDavid du Colombier Node t1, t2;
10533e12c5d1SDavid du Colombier
10543e12c5d1SDavid du Colombier while(c > 3) {
10553e12c5d1SDavid du Colombier layout(f, t, 2, 0, Z);
10563e12c5d1SDavid du Colombier c -= 2;
10573e12c5d1SDavid du Colombier }
10583e12c5d1SDavid du Colombier
10593e12c5d1SDavid du Colombier regalloc(&t1, ®node, Z);
10603e12c5d1SDavid du Colombier regalloc(&t2, ®node, Z);
10613e12c5d1SDavid du Colombier if(c > 0) {
10623e12c5d1SDavid du Colombier gopcode(OAS, f, Z, &t1);
1063219b2ee8SDavid du Colombier f->xoffset += SZ_LONG;
10643e12c5d1SDavid du Colombier }
10653e12c5d1SDavid du Colombier if(cn != Z)
10663e12c5d1SDavid du Colombier gopcode(OAS, nodconst(cv), Z, cn);
10673e12c5d1SDavid du Colombier if(c > 1) {
10683e12c5d1SDavid du Colombier gopcode(OAS, f, Z, &t2);
1069219b2ee8SDavid du Colombier f->xoffset += SZ_LONG;
10703e12c5d1SDavid du Colombier }
10713e12c5d1SDavid du Colombier if(c > 0) {
10723e12c5d1SDavid du Colombier gopcode(OAS, &t1, Z, t);
1073219b2ee8SDavid du Colombier t->xoffset += SZ_LONG;
10743e12c5d1SDavid du Colombier }
10753e12c5d1SDavid du Colombier if(c > 2) {
10763e12c5d1SDavid du Colombier gopcode(OAS, f, Z, &t1);
1077219b2ee8SDavid du Colombier f->xoffset += SZ_LONG;
10783e12c5d1SDavid du Colombier }
10793e12c5d1SDavid du Colombier if(c > 1) {
10803e12c5d1SDavid du Colombier gopcode(OAS, &t2, Z, t);
1081219b2ee8SDavid du Colombier t->xoffset += SZ_LONG;
10823e12c5d1SDavid du Colombier }
10833e12c5d1SDavid du Colombier if(c > 2) {
10843e12c5d1SDavid du Colombier gopcode(OAS, &t1, Z, t);
1085219b2ee8SDavid du Colombier t->xoffset += SZ_LONG;
10863e12c5d1SDavid du Colombier }
10873e12c5d1SDavid du Colombier regfree(&t1);
10883e12c5d1SDavid du Colombier regfree(&t2);
10893e12c5d1SDavid du Colombier }
1090