13e12c5d1SDavid du Colombier #include "gc.h" 23e12c5d1SDavid du Colombier 33e12c5d1SDavid du Colombier void 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; 97dd7cddfSDavid du Colombier int o, hardleft; 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; 253e12c5d1SDavid 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(l->complex >= FNX) 433e12c5d1SDavid du Colombier if(r != Z && r->complex >= FNX) 443e12c5d1SDavid du Colombier switch(o) { 453e12c5d1SDavid du Colombier default: 463e12c5d1SDavid du Colombier regret(&nod, r); 473e12c5d1SDavid du Colombier cgen(r, &nod); 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier regsalloc(&nod1, r); 503e12c5d1SDavid du Colombier gmove(&nod, &nod1); 513e12c5d1SDavid du Colombier 523e12c5d1SDavid du Colombier regfree(&nod); 533e12c5d1SDavid du Colombier nod = *n; 543e12c5d1SDavid du Colombier nod.right = &nod1; 553e12c5d1SDavid du Colombier 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 687dd7cddfSDavid du Colombier hardleft = l->addable < INDEXED || l->complex >= FNX; 693e12c5d1SDavid du Colombier switch(o) { 703e12c5d1SDavid du Colombier default: 713e12c5d1SDavid du Colombier diag(n, "unknown op in cgen: %O", o); 723e12c5d1SDavid du Colombier break; 733e12c5d1SDavid du Colombier 743e12c5d1SDavid du Colombier case OAS: 75219b2ee8SDavid du Colombier if(typefd[n->type->etype]) { 763e12c5d1SDavid du Colombier cgen(r, &fregnode0); 773e12c5d1SDavid du Colombier if(nn != Z) 783e12c5d1SDavid du Colombier gins(AFMOVD, &fregnode0, &fregnode0); 793e12c5d1SDavid du Colombier if(l->addable < INDEXED) { 803e12c5d1SDavid du Colombier reglcgen(&nod, l, Z); 813e12c5d1SDavid du Colombier gmove(&fregnode0, &nod); 823e12c5d1SDavid du Colombier regfree(&nod); 833e12c5d1SDavid du Colombier } else 843e12c5d1SDavid du Colombier gmove(&fregnode0, l); 853e12c5d1SDavid du Colombier if(nn != Z) 863e12c5d1SDavid du Colombier gmove(&fregnode0, nn); 873e12c5d1SDavid du Colombier return; 883e12c5d1SDavid du Colombier } 893e12c5d1SDavid du Colombier if(l->op == OBIT) 903e12c5d1SDavid du Colombier goto bitas; 917dd7cddfSDavid du Colombier if(!hardleft) { 923e12c5d1SDavid du Colombier if(nn != Z || r->addable < INDEXED) { 937dd7cddfSDavid du Colombier if(r->complex >= FNX && nn == Z) 947dd7cddfSDavid du Colombier regret(&nod, r); 957dd7cddfSDavid du Colombier else 963e12c5d1SDavid du Colombier regalloc(&nod, r, nn); 973e12c5d1SDavid du Colombier cgen(r, &nod); 983e12c5d1SDavid du Colombier gmove(&nod, l); 997dd7cddfSDavid du Colombier if(nn != Z) 1007dd7cddfSDavid du Colombier gmove(&nod, nn); 1013e12c5d1SDavid du Colombier regfree(&nod); 1023e12c5d1SDavid du Colombier } else 1033e12c5d1SDavid du Colombier gmove(r, l); 1043e12c5d1SDavid du Colombier break; 1053e12c5d1SDavid du Colombier } 1063e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 107*80ee5cbfSDavid du Colombier if(l->op == OINDEX && r->op == OCONST) { 108*80ee5cbfSDavid du Colombier gmove(r, l); 109*80ee5cbfSDavid du Colombier break; 110*80ee5cbfSDavid du Colombier } 1113e12c5d1SDavid du Colombier reglcgen(&nod1, l, Z); 1123e12c5d1SDavid du Colombier if(r->addable >= INDEXED) { 1133e12c5d1SDavid du Colombier gmove(r, &nod1); 1143e12c5d1SDavid du Colombier if(nn != Z) 1153e12c5d1SDavid du Colombier gmove(r, nn); 1163e12c5d1SDavid du Colombier regfree(&nod1); 1173e12c5d1SDavid du Colombier break; 1183e12c5d1SDavid du Colombier } 1193e12c5d1SDavid du Colombier regalloc(&nod, r, nn); 1203e12c5d1SDavid du Colombier cgen(r, &nod); 1213e12c5d1SDavid du Colombier } else { 1223e12c5d1SDavid du Colombier regalloc(&nod, r, nn); 1233e12c5d1SDavid du Colombier cgen(r, &nod); 1243e12c5d1SDavid du Colombier reglcgen(&nod1, l, Z); 1253e12c5d1SDavid du Colombier } 1263e12c5d1SDavid du Colombier gmove(&nod, &nod1); 1273e12c5d1SDavid du Colombier regfree(&nod); 1283e12c5d1SDavid du Colombier regfree(&nod1); 1293e12c5d1SDavid du Colombier break; 1303e12c5d1SDavid du Colombier 1313e12c5d1SDavid du Colombier bitas: 1323e12c5d1SDavid du Colombier n = l->left; 1333e12c5d1SDavid du Colombier regalloc(&nod, r, nn); 1343e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 1353e12c5d1SDavid du Colombier reglcgen(&nod1, n, Z); 1363e12c5d1SDavid du Colombier cgen(r, &nod); 1373e12c5d1SDavid du Colombier } else { 1383e12c5d1SDavid du Colombier cgen(r, &nod); 1393e12c5d1SDavid du Colombier reglcgen(&nod1, n, Z); 1403e12c5d1SDavid du Colombier } 1413e12c5d1SDavid du Colombier regalloc(&nod2, n, Z); 1423e12c5d1SDavid du Colombier gmove(&nod1, &nod2); 1433e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn); 1443e12c5d1SDavid du Colombier break; 1453e12c5d1SDavid du Colombier 1463e12c5d1SDavid du Colombier case OBIT: 1473e12c5d1SDavid du Colombier if(nn == Z) { 1483e12c5d1SDavid du Colombier nullwarn(l, Z); 1493e12c5d1SDavid du Colombier break; 1503e12c5d1SDavid du Colombier } 1513e12c5d1SDavid du Colombier bitload(n, &nod, Z, Z, nn); 1523e12c5d1SDavid du Colombier gmove(&nod, nn); 1533e12c5d1SDavid du Colombier regfree(&nod); 1543e12c5d1SDavid du Colombier break; 1553e12c5d1SDavid du Colombier 1563e12c5d1SDavid du Colombier case OLSHR: 1573e12c5d1SDavid du Colombier case OASHL: 1583e12c5d1SDavid du Colombier case OASHR: 1593e12c5d1SDavid du Colombier if(nn == Z) { 1603e12c5d1SDavid du Colombier nullwarn(l, r); 1613e12c5d1SDavid du Colombier break; 1623e12c5d1SDavid du Colombier } 1633e12c5d1SDavid du Colombier if(r->op == OCONST) { 164219b2ee8SDavid du Colombier if(r->vconst == 0) { 1653e12c5d1SDavid du Colombier cgen(l, nn); 1663e12c5d1SDavid du Colombier break; 1673e12c5d1SDavid du Colombier } 1683e12c5d1SDavid du Colombier regalloc(&nod, l, nn); 1693e12c5d1SDavid du Colombier cgen(l, &nod); 1703e12c5d1SDavid du Colombier gopcode(o, n->type, r, &nod); 1713e12c5d1SDavid du Colombier gmove(&nod, nn); 1723e12c5d1SDavid du Colombier regfree(&nod); 1733e12c5d1SDavid du Colombier break; 1743e12c5d1SDavid du Colombier } 1753e12c5d1SDavid du Colombier 1763e12c5d1SDavid du Colombier /* 1773e12c5d1SDavid du Colombier * get nod to be D_CX 1783e12c5d1SDavid du Colombier */ 1793e12c5d1SDavid du Colombier if(nodreg(&nod, nn, D_CX)) { 1803e12c5d1SDavid du Colombier regsalloc(&nod1, n); 1813e12c5d1SDavid du Colombier gmove(&nod, &nod1); 1823e12c5d1SDavid du Colombier cgen(n, &nod); /* probably a bug */ 1833e12c5d1SDavid du Colombier gmove(&nod, nn); 1843e12c5d1SDavid du Colombier gmove(&nod1, &nod); 1853e12c5d1SDavid du Colombier break; 1863e12c5d1SDavid du Colombier } 1873e12c5d1SDavid du Colombier reg[D_CX]++; 1883e12c5d1SDavid du Colombier if(nn->op == OREGISTER && nn->reg == D_CX) 1893e12c5d1SDavid du Colombier regalloc(&nod1, l, Z); 1903e12c5d1SDavid du Colombier else 1913e12c5d1SDavid du Colombier regalloc(&nod1, l, nn); 1923e12c5d1SDavid du Colombier if(r->complex >= l->complex) { 1933e12c5d1SDavid du Colombier cgen(r, &nod); 1943e12c5d1SDavid du Colombier cgen(l, &nod1); 1953e12c5d1SDavid du Colombier } else { 1963e12c5d1SDavid du Colombier cgen(l, &nod1); 1973e12c5d1SDavid du Colombier cgen(r, &nod); 1983e12c5d1SDavid du Colombier } 1993e12c5d1SDavid du Colombier gopcode(o, n->type, &nod, &nod1); 2003e12c5d1SDavid du Colombier gmove(&nod1, nn); 2013e12c5d1SDavid du Colombier regfree(&nod); 2023e12c5d1SDavid du Colombier regfree(&nod1); 2033e12c5d1SDavid du Colombier break; 2043e12c5d1SDavid du Colombier 2053e12c5d1SDavid du Colombier case OADD: 2063e12c5d1SDavid du Colombier case OSUB: 2073e12c5d1SDavid du Colombier case OOR: 2083e12c5d1SDavid du Colombier case OXOR: 2093e12c5d1SDavid du Colombier case OAND: 2103e12c5d1SDavid du Colombier if(nn == Z) { 2113e12c5d1SDavid du Colombier nullwarn(l, r); 2123e12c5d1SDavid du Colombier break; 2133e12c5d1SDavid du Colombier } 214219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 2153e12c5d1SDavid du Colombier goto fop; 216219b2ee8SDavid du Colombier if(r->op == OCONST) { 217219b2ee8SDavid du Colombier if(r->vconst == 0 && o != OAND) { 2183e12c5d1SDavid du Colombier cgen(l, nn); 2193e12c5d1SDavid du Colombier break; 2203e12c5d1SDavid du Colombier } 221219b2ee8SDavid du Colombier } 2223e12c5d1SDavid du Colombier if(r->addable >= INDEXED) { 2233e12c5d1SDavid du Colombier regalloc(&nod, l, nn); 2243e12c5d1SDavid du Colombier cgen(l, &nod); 2253e12c5d1SDavid du Colombier gopcode(o, n->type, r, &nod); 2263e12c5d1SDavid du Colombier gmove(&nod, nn); 2273e12c5d1SDavid du Colombier regfree(&nod); 2283e12c5d1SDavid du Colombier break; 2293e12c5d1SDavid du Colombier } 2303e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 2313e12c5d1SDavid du Colombier regalloc(&nod, l, nn); 2323e12c5d1SDavid du Colombier cgen(l, &nod); 2333e12c5d1SDavid du Colombier regalloc(&nod1, r, Z); 2343e12c5d1SDavid du Colombier cgen(r, &nod1); 2353e12c5d1SDavid du Colombier gopcode(o, n->type, &nod1, &nod); 2363e12c5d1SDavid du Colombier } else { 2373e12c5d1SDavid du Colombier regalloc(&nod1, r, nn); 2383e12c5d1SDavid du Colombier cgen(r, &nod1); 2393e12c5d1SDavid du Colombier regalloc(&nod, l, Z); 2403e12c5d1SDavid du Colombier cgen(l, &nod); 2413e12c5d1SDavid du Colombier gopcode(o, n->type, &nod1, &nod); 2423e12c5d1SDavid du Colombier } 2433e12c5d1SDavid du Colombier gmove(&nod, nn); 2443e12c5d1SDavid du Colombier regfree(&nod); 2453e12c5d1SDavid du Colombier regfree(&nod1); 2463e12c5d1SDavid du Colombier break; 2473e12c5d1SDavid du Colombier 2483e12c5d1SDavid du Colombier case OLMOD: 2493e12c5d1SDavid du Colombier case OMOD: 2503e12c5d1SDavid du Colombier case OLMUL: 2513e12c5d1SDavid du Colombier case OLDIV: 2523e12c5d1SDavid du Colombier case OMUL: 2533e12c5d1SDavid du Colombier case ODIV: 2543e12c5d1SDavid du Colombier if(nn == Z) { 2553e12c5d1SDavid du Colombier nullwarn(l, r); 2563e12c5d1SDavid du Colombier break; 2573e12c5d1SDavid du Colombier } 258219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 2593e12c5d1SDavid du Colombier goto fop; 2603e12c5d1SDavid du Colombier /* 2613e12c5d1SDavid du Colombier * get nod to be D_AX 2623e12c5d1SDavid du Colombier * get nod1 to be D_DX 2633e12c5d1SDavid du Colombier */ 2643e12c5d1SDavid du Colombier if(nodreg(&nod, nn, D_AX)) { 2653e12c5d1SDavid du Colombier regsalloc(&nod2, n); 2663e12c5d1SDavid du Colombier gmove(&nod, &nod2); 2673e12c5d1SDavid du Colombier v = reg[D_AX]; 2683e12c5d1SDavid du Colombier reg[D_AX] = 0; 2693e12c5d1SDavid du Colombier 2703e12c5d1SDavid du Colombier if(isreg(l, D_AX)) { 2713e12c5d1SDavid du Colombier nod3 = *n; 2723e12c5d1SDavid du Colombier nod3.left = &nod2; 2733e12c5d1SDavid du Colombier cgen(&nod3, nn); 2743e12c5d1SDavid du Colombier } else 2753e12c5d1SDavid du Colombier if(isreg(r, D_AX)) { 2763e12c5d1SDavid du Colombier nod3 = *n; 2773e12c5d1SDavid du Colombier nod3.right = &nod2; 2783e12c5d1SDavid du Colombier cgen(&nod3, nn); 2793e12c5d1SDavid du Colombier } else 2803e12c5d1SDavid du Colombier cgen(n, nn); 2813e12c5d1SDavid du Colombier 2823e12c5d1SDavid du Colombier gmove(&nod2, &nod); 2833e12c5d1SDavid du Colombier reg[D_AX] = v; 2843e12c5d1SDavid du Colombier break; 2853e12c5d1SDavid du Colombier } 2863e12c5d1SDavid du Colombier if(nodreg(&nod1, nn, D_DX)) { 2873e12c5d1SDavid du Colombier regsalloc(&nod2, n); 2883e12c5d1SDavid du Colombier gmove(&nod1, &nod2); 2893e12c5d1SDavid du Colombier v = reg[D_DX]; 2903e12c5d1SDavid du Colombier reg[D_DX] = 0; 2913e12c5d1SDavid du Colombier 2923e12c5d1SDavid du Colombier if(isreg(l, D_DX)) { 2933e12c5d1SDavid du Colombier nod3 = *n; 2943e12c5d1SDavid du Colombier nod3.left = &nod2; 2953e12c5d1SDavid du Colombier cgen(&nod3, nn); 2963e12c5d1SDavid du Colombier } else 2973e12c5d1SDavid du Colombier if(isreg(r, D_DX)) { 2983e12c5d1SDavid du Colombier nod3 = *n; 2993e12c5d1SDavid du Colombier nod3.right = &nod2; 3003e12c5d1SDavid du Colombier cgen(&nod3, nn); 3013e12c5d1SDavid du Colombier } else 3023e12c5d1SDavid du Colombier cgen(n, nn); 3033e12c5d1SDavid du Colombier 3043e12c5d1SDavid du Colombier gmove(&nod2, &nod1); 3053e12c5d1SDavid du Colombier reg[D_DX] = v; 3063e12c5d1SDavid du Colombier break; 3073e12c5d1SDavid du Colombier } 3083e12c5d1SDavid du Colombier reg[D_AX]++; 3093e12c5d1SDavid du Colombier 3103e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 3113e12c5d1SDavid du Colombier cgen(l, &nod); 3123e12c5d1SDavid du Colombier reg[D_DX]++; 3133e12c5d1SDavid du Colombier if(o == ODIV || o == OMOD) 3143e12c5d1SDavid du Colombier gins(ACDQ, Z, Z); 3153e12c5d1SDavid du Colombier if(o == OLDIV || o == OLMOD) 3163e12c5d1SDavid du Colombier gins(AMOVL, nodconst(0), &nod1); 3173e12c5d1SDavid du Colombier if(r->addable < INDEXED || r->op == OCONST) { 3183e12c5d1SDavid du Colombier regsalloc(&nod3, r); 3193e12c5d1SDavid du Colombier cgen(r, &nod3); 3203e12c5d1SDavid du Colombier gopcode(o, n->type, &nod3, Z); 3213e12c5d1SDavid du Colombier } else 3223e12c5d1SDavid du Colombier gopcode(o, n->type, r, Z); 3233e12c5d1SDavid du Colombier } else { 3243e12c5d1SDavid du Colombier regsalloc(&nod3, r); 3253e12c5d1SDavid du Colombier cgen(r, &nod3); 3263e12c5d1SDavid du Colombier cgen(l, &nod); 3273e12c5d1SDavid du Colombier reg[D_DX]++; 3283e12c5d1SDavid du Colombier if(o == ODIV || o == OMOD) 3293e12c5d1SDavid du Colombier gins(ACDQ, Z, Z); 3303e12c5d1SDavid du Colombier if(o == OLDIV || o == OLMOD) 3313e12c5d1SDavid du Colombier gins(AMOVL, nodconst(0), &nod1); 3323e12c5d1SDavid du Colombier gopcode(o, n->type, &nod3, Z); 3333e12c5d1SDavid du Colombier } 3343e12c5d1SDavid du Colombier if(o == OMOD || o == OLMOD) 3353e12c5d1SDavid du Colombier gmove(&nod1, nn); 3363e12c5d1SDavid du Colombier else 3373e12c5d1SDavid du Colombier gmove(&nod, nn); 3383e12c5d1SDavid du Colombier regfree(&nod); 3393e12c5d1SDavid du Colombier regfree(&nod1); 3403e12c5d1SDavid du Colombier break; 3413e12c5d1SDavid du Colombier 3423e12c5d1SDavid du Colombier case OASLSHR: 3433e12c5d1SDavid du Colombier case OASASHL: 3443e12c5d1SDavid du Colombier case OASASHR: 3453e12c5d1SDavid du Colombier if(r->op == OCONST) 3463e12c5d1SDavid du Colombier goto asand; 3473e12c5d1SDavid du Colombier if(l->op == OBIT) 3483e12c5d1SDavid du Colombier goto asbitop; 349219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 3503e12c5d1SDavid du Colombier goto asfop; 3513e12c5d1SDavid du Colombier 3523e12c5d1SDavid du Colombier /* 3533e12c5d1SDavid du Colombier * get nod to be D_CX 3543e12c5d1SDavid du Colombier */ 3553e12c5d1SDavid du Colombier if(nodreg(&nod, nn, D_CX)) { 3563e12c5d1SDavid du Colombier regsalloc(&nod1, n); 3573e12c5d1SDavid du Colombier gmove(&nod, &nod1); 3583e12c5d1SDavid du Colombier cgen(n, &nod); 3593e12c5d1SDavid du Colombier if(nn != Z) 3603e12c5d1SDavid du Colombier gmove(&nod, nn); 3613e12c5d1SDavid du Colombier gmove(&nod1, &nod); 3623e12c5d1SDavid du Colombier break; 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier reg[D_CX]++; 3653e12c5d1SDavid du Colombier 3663e12c5d1SDavid du Colombier if(r->complex >= l->complex) { 3673e12c5d1SDavid du Colombier cgen(r, &nod); 3687dd7cddfSDavid du Colombier if(hardleft) 3693e12c5d1SDavid du Colombier reglcgen(&nod1, l, Z); 3703e12c5d1SDavid du Colombier else 3713e12c5d1SDavid du Colombier nod1 = *l; 3723e12c5d1SDavid du Colombier } else { 3737dd7cddfSDavid du Colombier if(hardleft) 3743e12c5d1SDavid du Colombier reglcgen(&nod1, l, Z); 3753e12c5d1SDavid du Colombier else 3763e12c5d1SDavid du Colombier nod1 = *l; 3773e12c5d1SDavid du Colombier cgen(r, &nod); 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier 3803e12c5d1SDavid du Colombier gopcode(o, l->type, &nod, &nod1); 3813e12c5d1SDavid du Colombier regfree(&nod); 3823e12c5d1SDavid du Colombier if(nn != Z) 3833e12c5d1SDavid du Colombier gmove(&nod1, nn); 3847dd7cddfSDavid du Colombier if(hardleft) 3853e12c5d1SDavid du Colombier regfree(&nod1); 3863e12c5d1SDavid du Colombier break; 3873e12c5d1SDavid du Colombier 3883e12c5d1SDavid du Colombier case OASAND: 3893e12c5d1SDavid du Colombier case OASADD: 3903e12c5d1SDavid du Colombier case OASSUB: 3913e12c5d1SDavid du Colombier case OASXOR: 3923e12c5d1SDavid du Colombier case OASOR: 3933e12c5d1SDavid du Colombier asand: 3943e12c5d1SDavid du Colombier if(l->op == OBIT) 3953e12c5d1SDavid du Colombier goto asbitop; 396219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 3973e12c5d1SDavid du Colombier goto asfop; 3983e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 3997dd7cddfSDavid du Colombier if(hardleft) 4003e12c5d1SDavid du Colombier reglcgen(&nod, l, Z); 4013e12c5d1SDavid du Colombier else 4023e12c5d1SDavid du Colombier nod = *l; 4033e12c5d1SDavid du Colombier if(r->op != OCONST) { 4043e12c5d1SDavid du Colombier regalloc(&nod1, r, nn); 4053e12c5d1SDavid du Colombier cgen(r, &nod1); 4063e12c5d1SDavid du Colombier gopcode(o, l->type, &nod1, &nod); 4073e12c5d1SDavid du Colombier regfree(&nod1); 4083e12c5d1SDavid du Colombier } else 4093e12c5d1SDavid du Colombier gopcode(o, l->type, r, &nod); 4103e12c5d1SDavid du Colombier } else { 4113e12c5d1SDavid du Colombier regalloc(&nod1, r, nn); 4123e12c5d1SDavid du Colombier cgen(r, &nod1); 4137dd7cddfSDavid du Colombier if(hardleft) 4143e12c5d1SDavid du Colombier reglcgen(&nod, l, Z); 4153e12c5d1SDavid du Colombier else 4163e12c5d1SDavid du Colombier nod = *l; 417219b2ee8SDavid du Colombier gopcode(o, l->type, &nod1, &nod); 4183e12c5d1SDavid du Colombier regfree(&nod1); 4193e12c5d1SDavid du Colombier } 4203e12c5d1SDavid du Colombier if(nn != Z) 4213e12c5d1SDavid du Colombier gmove(&nod, nn); 4227dd7cddfSDavid du Colombier if(hardleft) 4233e12c5d1SDavid du Colombier regfree(&nod); 4243e12c5d1SDavid du Colombier break; 4253e12c5d1SDavid du Colombier 4263e12c5d1SDavid du Colombier case OASLMUL: 4273e12c5d1SDavid du Colombier case OASLDIV: 4283e12c5d1SDavid du Colombier case OASLMOD: 4293e12c5d1SDavid du Colombier case OASMUL: 4303e12c5d1SDavid du Colombier case OASDIV: 4313e12c5d1SDavid du Colombier case OASMOD: 4323e12c5d1SDavid du Colombier if(l->op == OBIT) 4333e12c5d1SDavid du Colombier goto asbitop; 434219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 4353e12c5d1SDavid du Colombier goto asfop; 4363e12c5d1SDavid du Colombier /* 4373e12c5d1SDavid du Colombier * get nod to be D_AX 4383e12c5d1SDavid du Colombier * get nod1 to be D_DX 4393e12c5d1SDavid du Colombier */ 4403e12c5d1SDavid du Colombier if(nodreg(&nod, nn, D_AX)) { 4413e12c5d1SDavid du Colombier regsalloc(&nod2, n); 4423e12c5d1SDavid du Colombier gmove(&nod, &nod2); 4433e12c5d1SDavid du Colombier v = reg[D_AX]; 4443e12c5d1SDavid du Colombier reg[D_AX] = 0; 4453e12c5d1SDavid du Colombier 4463e12c5d1SDavid du Colombier if(isreg(l, D_AX)) { 4473e12c5d1SDavid du Colombier nod3 = *n; 4483e12c5d1SDavid du Colombier nod3.left = &nod2; 4493e12c5d1SDavid du Colombier cgen(&nod3, nn); 4503e12c5d1SDavid du Colombier } else 4513e12c5d1SDavid du Colombier if(isreg(r, D_AX)) { 4523e12c5d1SDavid du Colombier nod3 = *n; 4533e12c5d1SDavid du Colombier nod3.right = &nod2; 4543e12c5d1SDavid du Colombier cgen(&nod3, nn); 4553e12c5d1SDavid du Colombier } else 4563e12c5d1SDavid du Colombier cgen(n, nn); 4573e12c5d1SDavid du Colombier 4583e12c5d1SDavid du Colombier gmove(&nod2, &nod); 4593e12c5d1SDavid du Colombier reg[D_AX] = v; 4603e12c5d1SDavid du Colombier break; 4613e12c5d1SDavid du Colombier } 4623e12c5d1SDavid du Colombier if(nodreg(&nod1, nn, D_DX)) { 4633e12c5d1SDavid du Colombier regsalloc(&nod2, n); 4643e12c5d1SDavid du Colombier gmove(&nod1, &nod2); 4653e12c5d1SDavid du Colombier v = reg[D_DX]; 4663e12c5d1SDavid du Colombier reg[D_DX] = 0; 4673e12c5d1SDavid du Colombier 4683e12c5d1SDavid du Colombier if(isreg(l, D_DX)) { 4693e12c5d1SDavid du Colombier nod3 = *n; 4703e12c5d1SDavid du Colombier nod3.left = &nod2; 4713e12c5d1SDavid du Colombier cgen(&nod3, nn); 4723e12c5d1SDavid du Colombier } else 4733e12c5d1SDavid du Colombier if(isreg(r, D_DX)) { 4743e12c5d1SDavid du Colombier nod3 = *n; 4753e12c5d1SDavid du Colombier nod3.right = &nod2; 4763e12c5d1SDavid du Colombier cgen(&nod3, nn); 4773e12c5d1SDavid du Colombier } else 4783e12c5d1SDavid du Colombier cgen(n, nn); 4793e12c5d1SDavid du Colombier 4803e12c5d1SDavid du Colombier gmove(&nod2, &nod1); 4813e12c5d1SDavid du Colombier reg[D_DX] = v; 4823e12c5d1SDavid du Colombier break; 4833e12c5d1SDavid du Colombier } 4843e12c5d1SDavid du Colombier reg[D_AX]++; 4853e12c5d1SDavid du Colombier reg[D_DX]++; 4863e12c5d1SDavid du Colombier 4873e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 4887dd7cddfSDavid du Colombier if(hardleft) 4893e12c5d1SDavid du Colombier reglcgen(&nod2, l, Z); 4903e12c5d1SDavid du Colombier else 4913e12c5d1SDavid du Colombier nod2 = *l; 4923e12c5d1SDavid du Colombier cgen(&nod2, &nod); 4933e12c5d1SDavid du Colombier if(o == OASDIV || o == OASMOD) 4943e12c5d1SDavid du Colombier gins(ACDQ, Z, Z); 4953e12c5d1SDavid du Colombier if(o == OASLDIV || o == OASLMOD) 4963e12c5d1SDavid du Colombier gins(AMOVL, nodconst(0), &nod1); 4973e12c5d1SDavid du Colombier if(r->addable < INDEXED || r->op == OCONST || 4987dd7cddfSDavid du Colombier !typeil[r->type->etype]) { 4993e12c5d1SDavid du Colombier regalloc(&nod3, r, Z); 5003e12c5d1SDavid du Colombier cgen(r, &nod3); 5013e12c5d1SDavid du Colombier gopcode(o, l->type, &nod3, Z); 5023e12c5d1SDavid du Colombier regfree(&nod3); 5033e12c5d1SDavid du Colombier } else 5043e12c5d1SDavid du Colombier gopcode(o, n->type, r, Z); 5053e12c5d1SDavid du Colombier } else { 5063e12c5d1SDavid du Colombier regalloc(&nod3, r, Z); 5073e12c5d1SDavid du Colombier cgen(r, &nod3); 5087dd7cddfSDavid du Colombier if(hardleft) 5093e12c5d1SDavid du Colombier reglcgen(&nod2, l, Z); 5103e12c5d1SDavid du Colombier else 5113e12c5d1SDavid du Colombier nod2 = *l; 5123e12c5d1SDavid du Colombier cgen(&nod2, &nod); 5133e12c5d1SDavid du Colombier if(o == OASDIV || o == OASMOD) 5143e12c5d1SDavid du Colombier gins(ACDQ, Z, Z); 5153e12c5d1SDavid du Colombier if(o == OASLDIV || o == OASLMOD) 5163e12c5d1SDavid du Colombier gins(AMOVL, nodconst(0), &nod1); 5173e12c5d1SDavid du Colombier gopcode(o, l->type, &nod3, Z); 5183e12c5d1SDavid du Colombier regfree(&nod3); 5193e12c5d1SDavid du Colombier } 5203e12c5d1SDavid du Colombier if(o == OASMOD || o == OASLMOD) { 5213e12c5d1SDavid du Colombier gmove(&nod1, &nod2); 5223e12c5d1SDavid du Colombier if(nn != Z) 5233e12c5d1SDavid du Colombier gmove(&nod1, nn); 5243e12c5d1SDavid du Colombier } else { 5253e12c5d1SDavid du Colombier gmove(&nod, &nod2); 5263e12c5d1SDavid du Colombier if(nn != Z) 5273e12c5d1SDavid du Colombier gmove(&nod, nn); 5283e12c5d1SDavid du Colombier } 5297dd7cddfSDavid du Colombier if(hardleft) 5303e12c5d1SDavid du Colombier regfree(&nod2); 5313e12c5d1SDavid du Colombier regfree(&nod); 5323e12c5d1SDavid du Colombier regfree(&nod1); 5333e12c5d1SDavid du Colombier break; 5343e12c5d1SDavid du Colombier 5353e12c5d1SDavid du Colombier fop: 5363e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 5373e12c5d1SDavid du Colombier cgen(l, &fregnode0); 5383e12c5d1SDavid du Colombier if(r->addable < INDEXED) { 5393e12c5d1SDavid du Colombier cgen(r, &fregnode0); 5403e12c5d1SDavid du Colombier fgopcode(o, &fregnode0, &fregnode1, 1, 0); 5413e12c5d1SDavid du Colombier } else 5423e12c5d1SDavid du Colombier fgopcode(o, r, &fregnode0, 0, 0); 5433e12c5d1SDavid du Colombier } else { 5443e12c5d1SDavid du Colombier cgen(r, &fregnode0); 5453e12c5d1SDavid du Colombier if(l->addable < INDEXED) { 5463e12c5d1SDavid du Colombier cgen(l, &fregnode0); 5473e12c5d1SDavid du Colombier fgopcode(o, &fregnode0, &fregnode1, 1, 1); 5483e12c5d1SDavid du Colombier } else 5493e12c5d1SDavid du Colombier fgopcode(o, l, &fregnode0, 0, 1); 5503e12c5d1SDavid du Colombier } 5513e12c5d1SDavid du Colombier gmove(&fregnode0, nn); 5523e12c5d1SDavid du Colombier break; 5533e12c5d1SDavid du Colombier 5543e12c5d1SDavid du Colombier asfop: 5553e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 5567dd7cddfSDavid du Colombier if(hardleft) 5573e12c5d1SDavid du Colombier reglcgen(&nod, l, Z); 5583e12c5d1SDavid du Colombier else 5593e12c5d1SDavid du Colombier nod = *l; 5603e12c5d1SDavid du Colombier cgen(r, &fregnode0); 5613e12c5d1SDavid du Colombier } else { 5623e12c5d1SDavid du Colombier cgen(r, &fregnode0); 5637dd7cddfSDavid du Colombier if(hardleft) 5643e12c5d1SDavid du Colombier reglcgen(&nod, l, Z); 5653e12c5d1SDavid du Colombier else 5663e12c5d1SDavid du Colombier nod = *l; 5673e12c5d1SDavid du Colombier } 568219b2ee8SDavid du Colombier if(!typefd[l->type->etype]) { 5693e12c5d1SDavid du Colombier gmove(&nod, &fregnode0); 5703e12c5d1SDavid du Colombier fgopcode(o, &fregnode0, &fregnode1, 1, 1); 5713e12c5d1SDavid du Colombier } else 5723e12c5d1SDavid du Colombier fgopcode(o, &nod, &fregnode0, 0, 1); 5733e12c5d1SDavid du Colombier if(nn != Z) 5743e12c5d1SDavid du Colombier gins(AFMOVD, &fregnode0, &fregnode0); 5753e12c5d1SDavid du Colombier gmove(&fregnode0, &nod); 5763e12c5d1SDavid du Colombier if(nn != Z) 5773e12c5d1SDavid du Colombier gmove(&fregnode0, nn); 5787dd7cddfSDavid du Colombier if(hardleft) 5793e12c5d1SDavid du Colombier regfree(&nod); 5803e12c5d1SDavid du Colombier break; 5813e12c5d1SDavid du Colombier 5823e12c5d1SDavid du Colombier asbitop: 5833e12c5d1SDavid du Colombier regalloc(&nod4, n, nn); 5843e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 5853e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4); 5863e12c5d1SDavid du Colombier regalloc(&nod3, r, Z); 5873e12c5d1SDavid du Colombier cgen(r, &nod3); 5883e12c5d1SDavid du Colombier } else { 5893e12c5d1SDavid du Colombier regalloc(&nod3, r, Z); 5903e12c5d1SDavid du Colombier cgen(r, &nod3); 5913e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4); 5923e12c5d1SDavid du Colombier } 5933e12c5d1SDavid du Colombier gmove(&nod, &nod4); 5943e12c5d1SDavid du Colombier 595219b2ee8SDavid du Colombier if(typefd[nod3.type->etype]) 5963e12c5d1SDavid du Colombier fgopcode(o, &fregnode0, &fregnode1, 1, 1); 5973e12c5d1SDavid du Colombier else { 5983e12c5d1SDavid du Colombier Node onod; 5993e12c5d1SDavid du Colombier 6003e12c5d1SDavid du Colombier /* incredible grot ... */ 6013e12c5d1SDavid du Colombier onod = nod3; 6023e12c5d1SDavid du Colombier onod.op = o; 6033e12c5d1SDavid du Colombier onod.complex = 2; 6043e12c5d1SDavid du Colombier onod.addable = 0; 6057dd7cddfSDavid du Colombier onod.type = tfield; 6063e12c5d1SDavid du Colombier onod.left = &nod4; 6073e12c5d1SDavid du Colombier onod.right = &nod3; 6083e12c5d1SDavid du Colombier cgen(&onod, Z); 6093e12c5d1SDavid du Colombier } 6103e12c5d1SDavid du Colombier regfree(&nod3); 6113e12c5d1SDavid du Colombier gmove(&nod4, &nod); 6123e12c5d1SDavid du Colombier regfree(&nod4); 6133e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn); 6143e12c5d1SDavid du Colombier break; 6153e12c5d1SDavid du Colombier 6163e12c5d1SDavid du Colombier case OADDR: 6173e12c5d1SDavid du Colombier if(nn == Z) { 6183e12c5d1SDavid du Colombier nullwarn(l, Z); 6193e12c5d1SDavid du Colombier break; 6203e12c5d1SDavid du Colombier } 6213e12c5d1SDavid du Colombier lcgen(l, nn); 6223e12c5d1SDavid du Colombier break; 6233e12c5d1SDavid du Colombier 6243e12c5d1SDavid du Colombier case OFUNC: 6253e12c5d1SDavid du Colombier if(l->complex >= FNX) { 6263e12c5d1SDavid du Colombier if(l->op != OIND) 6273e12c5d1SDavid du Colombier diag(n, "bad function call"); 6283e12c5d1SDavid du Colombier 6293e12c5d1SDavid du Colombier regret(&nod, l->left); 6303e12c5d1SDavid du Colombier cgen(l->left, &nod); 6313e12c5d1SDavid du Colombier regsalloc(&nod1, l->left); 6323e12c5d1SDavid du Colombier gmove(&nod, &nod1); 6333e12c5d1SDavid du Colombier regfree(&nod); 6343e12c5d1SDavid du Colombier 6353e12c5d1SDavid du Colombier nod = *n; 6363e12c5d1SDavid du Colombier nod.left = &nod2; 6373e12c5d1SDavid du Colombier nod2 = *l; 6383e12c5d1SDavid du Colombier nod2.left = &nod1; 6393e12c5d1SDavid du Colombier nod2.complex = 1; 6403e12c5d1SDavid du Colombier cgen(&nod, nn); 6413e12c5d1SDavid du Colombier 6423e12c5d1SDavid du Colombier return; 6433e12c5d1SDavid du Colombier } 6443e12c5d1SDavid du Colombier gargs(r, &nod, &nod1); 6453e12c5d1SDavid du Colombier if(l->addable < INDEXED) { 6463e12c5d1SDavid du Colombier reglcgen(&nod, l, nn); 6473e12c5d1SDavid du Colombier nod.op = OREGISTER; 6483e12c5d1SDavid du Colombier gopcode(OFUNC, n->type, Z, &nod); 6493e12c5d1SDavid du Colombier regfree(&nod); 6503e12c5d1SDavid du Colombier } else 6513e12c5d1SDavid du Colombier gopcode(OFUNC, n->type, Z, l); 6523e12c5d1SDavid du Colombier if(REGARG && reg[REGARG]) 6533e12c5d1SDavid du Colombier reg[REGARG]--; 6543e12c5d1SDavid du Colombier if(nn != Z) { 6553e12c5d1SDavid du Colombier regret(&nod, n); 6563e12c5d1SDavid du Colombier gmove(&nod, nn); 6573e12c5d1SDavid du Colombier regfree(&nod); 6583e12c5d1SDavid du Colombier } else 659219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 6603e12c5d1SDavid du Colombier gins(AFMOVDP, &fregnode0, &fregnode0); 6613e12c5d1SDavid du Colombier break; 6623e12c5d1SDavid du Colombier 6633e12c5d1SDavid du Colombier case OIND: 6643e12c5d1SDavid du Colombier if(nn == Z) { 6653e12c5d1SDavid du Colombier nullwarn(l, Z); 6663e12c5d1SDavid du Colombier break; 6673e12c5d1SDavid du Colombier } 6683e12c5d1SDavid du Colombier regialloc(&nod, n, nn); 6693e12c5d1SDavid du Colombier r = l; 6703e12c5d1SDavid du Colombier while(r->op == OADD) 6713e12c5d1SDavid du Colombier r = r->right; 6723e12c5d1SDavid du Colombier if(sconst(r)) { 673219b2ee8SDavid du Colombier v = r->vconst; 674219b2ee8SDavid du Colombier r->vconst = 0; 6753e12c5d1SDavid du Colombier cgen(l, &nod); 676219b2ee8SDavid du Colombier nod.xoffset += v; 677219b2ee8SDavid du Colombier r->vconst = v; 6783e12c5d1SDavid du Colombier } else 6793e12c5d1SDavid du Colombier cgen(l, &nod); 6803e12c5d1SDavid du Colombier regind(&nod, n); 6813e12c5d1SDavid du Colombier gmove(&nod, nn); 6823e12c5d1SDavid du Colombier regfree(&nod); 6833e12c5d1SDavid du Colombier break; 6843e12c5d1SDavid du Colombier 6853e12c5d1SDavid du Colombier case OEQ: 6863e12c5d1SDavid du Colombier case ONE: 6873e12c5d1SDavid du Colombier case OLE: 6883e12c5d1SDavid du Colombier case OLT: 6893e12c5d1SDavid du Colombier case OGE: 6903e12c5d1SDavid du Colombier case OGT: 6913e12c5d1SDavid du Colombier case OLO: 6923e12c5d1SDavid du Colombier case OLS: 6933e12c5d1SDavid du Colombier case OHI: 6943e12c5d1SDavid du Colombier case OHS: 6953e12c5d1SDavid du Colombier if(nn == Z) { 6963e12c5d1SDavid du Colombier nullwarn(l, r); 6973e12c5d1SDavid du Colombier break; 6983e12c5d1SDavid du Colombier } 6993e12c5d1SDavid du Colombier boolgen(n, 1, nn); 7003e12c5d1SDavid du Colombier break; 7013e12c5d1SDavid du Colombier 7023e12c5d1SDavid du Colombier case OANDAND: 7033e12c5d1SDavid du Colombier case OOROR: 7043e12c5d1SDavid du Colombier boolgen(n, 1, nn); 7053e12c5d1SDavid du Colombier if(nn == Z) 7063e12c5d1SDavid du Colombier patch(p, pc); 7073e12c5d1SDavid du Colombier break; 7083e12c5d1SDavid du Colombier 7093e12c5d1SDavid du Colombier case ONOT: 7103e12c5d1SDavid du Colombier if(nn == Z) { 7113e12c5d1SDavid du Colombier nullwarn(l, Z); 7123e12c5d1SDavid du Colombier break; 7133e12c5d1SDavid du Colombier } 7143e12c5d1SDavid du Colombier boolgen(n, 1, nn); 7153e12c5d1SDavid du Colombier break; 7163e12c5d1SDavid du Colombier 7173e12c5d1SDavid du Colombier case OCOMMA: 7183e12c5d1SDavid du Colombier cgen(l, Z); 7193e12c5d1SDavid du Colombier cgen(r, nn); 7203e12c5d1SDavid du Colombier break; 7213e12c5d1SDavid du Colombier 7223e12c5d1SDavid du Colombier case OCAST: 7233e12c5d1SDavid du Colombier if(nn == Z) { 7243e12c5d1SDavid du Colombier nullwarn(l, Z); 7253e12c5d1SDavid du Colombier break; 7263e12c5d1SDavid du Colombier } 7273e12c5d1SDavid du Colombier /* 7283e12c5d1SDavid du Colombier * convert from types l->n->nn 7293e12c5d1SDavid du Colombier */ 7303e12c5d1SDavid du Colombier if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { 7313e12c5d1SDavid du Colombier /* both null, gen l->nn */ 7323e12c5d1SDavid du Colombier cgen(l, nn); 7333e12c5d1SDavid du Colombier break; 7343e12c5d1SDavid du Colombier } 7353e12c5d1SDavid du Colombier regalloc(&nod, l, nn); 7363e12c5d1SDavid du Colombier cgen(l, &nod); 7373e12c5d1SDavid du Colombier regalloc(&nod1, n, &nod); 7383e12c5d1SDavid du Colombier gmove(&nod, &nod1); 7393e12c5d1SDavid du Colombier gmove(&nod1, nn); 7403e12c5d1SDavid du Colombier regfree(&nod1); 7413e12c5d1SDavid du Colombier regfree(&nod); 7423e12c5d1SDavid du Colombier break; 7433e12c5d1SDavid du Colombier 7443e12c5d1SDavid du Colombier case ODOT: 7453e12c5d1SDavid du Colombier sugen(l, nodrat, l->type->width); 7467dd7cddfSDavid du Colombier if(nn == Z) 7477dd7cddfSDavid du Colombier break; 7483e12c5d1SDavid du Colombier warn(n, "non-interruptable temporary"); 7493e12c5d1SDavid du Colombier nod = *nodrat; 7503e12c5d1SDavid du Colombier if(!r || r->op != OCONST) { 7513e12c5d1SDavid du Colombier diag(n, "DOT and no offset"); 7523e12c5d1SDavid du Colombier break; 7533e12c5d1SDavid du Colombier } 754219b2ee8SDavid du Colombier nod.xoffset += (long)r->vconst; 7553e12c5d1SDavid du Colombier nod.type = n->type; 7563e12c5d1SDavid du Colombier cgen(&nod, nn); 7573e12c5d1SDavid du Colombier break; 7583e12c5d1SDavid du Colombier 7593e12c5d1SDavid du Colombier case OCOND: 7603e12c5d1SDavid du Colombier bcgen(l, 1); 7613e12c5d1SDavid du Colombier p1 = p; 7623e12c5d1SDavid du Colombier cgen(r->left, nn); 7633e12c5d1SDavid du Colombier gbranch(OGOTO); 7643e12c5d1SDavid du Colombier patch(p1, pc); 7653e12c5d1SDavid du Colombier p1 = p; 7663e12c5d1SDavid du Colombier cgen(r->right, nn); 7673e12c5d1SDavid du Colombier patch(p1, pc); 7683e12c5d1SDavid du Colombier break; 7693e12c5d1SDavid du Colombier 7703e12c5d1SDavid du Colombier case OPOSTINC: 7713e12c5d1SDavid du Colombier case OPOSTDEC: 7723e12c5d1SDavid du Colombier v = 1; 7733e12c5d1SDavid du Colombier if(l->type->etype == TIND) 7743e12c5d1SDavid du Colombier v = l->type->link->width; 7753e12c5d1SDavid du Colombier if(o == OPOSTDEC) 7763e12c5d1SDavid du Colombier v = -v; 7773e12c5d1SDavid du Colombier if(l->op == OBIT) 7783e12c5d1SDavid du Colombier goto bitinc; 7793e12c5d1SDavid du Colombier if(nn == Z) 7803e12c5d1SDavid du Colombier goto pre; 7813e12c5d1SDavid du Colombier 7827dd7cddfSDavid du Colombier if(hardleft) 7833e12c5d1SDavid du Colombier reglcgen(&nod, l, Z); 7843e12c5d1SDavid du Colombier else 7853e12c5d1SDavid du Colombier nod = *l; 7863e12c5d1SDavid du Colombier 787219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 7883e12c5d1SDavid du Colombier goto fltinc; 7893e12c5d1SDavid du Colombier gmove(&nod, nn); 7903e12c5d1SDavid du Colombier gopcode(OADD, n->type, nodconst(v), &nod); 7917dd7cddfSDavid du Colombier if(hardleft) 7923e12c5d1SDavid du Colombier regfree(&nod); 7933e12c5d1SDavid du Colombier break; 7943e12c5d1SDavid du Colombier 7953e12c5d1SDavid du Colombier case OPREINC: 7963e12c5d1SDavid du Colombier case OPREDEC: 7973e12c5d1SDavid du Colombier v = 1; 7983e12c5d1SDavid du Colombier if(l->type->etype == TIND) 7993e12c5d1SDavid du Colombier v = l->type->link->width; 8003e12c5d1SDavid du Colombier if(o == OPREDEC) 8013e12c5d1SDavid du Colombier v = -v; 8023e12c5d1SDavid du Colombier if(l->op == OBIT) 8033e12c5d1SDavid du Colombier goto bitinc; 8043e12c5d1SDavid du Colombier 8053e12c5d1SDavid du Colombier pre: 8067dd7cddfSDavid du Colombier if(hardleft) 8073e12c5d1SDavid du Colombier reglcgen(&nod, l, Z); 8083e12c5d1SDavid du Colombier else 8093e12c5d1SDavid du Colombier nod = *l; 810219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 8113e12c5d1SDavid du Colombier goto fltinc; 8123e12c5d1SDavid du Colombier gopcode(OADD, n->type, nodconst(v), &nod); 8133e12c5d1SDavid du Colombier if(nn != Z) 8143e12c5d1SDavid du Colombier gmove(&nod, nn); 8157dd7cddfSDavid du Colombier if(hardleft) 8163e12c5d1SDavid du Colombier regfree(&nod); 8173e12c5d1SDavid du Colombier break; 8183e12c5d1SDavid du Colombier 8193e12c5d1SDavid du Colombier fltinc: 8203e12c5d1SDavid du Colombier gmove(&nod, &fregnode0); 8213e12c5d1SDavid du Colombier if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) 8223e12c5d1SDavid du Colombier gins(AFMOVD, &fregnode0, &fregnode0); 8233e12c5d1SDavid du Colombier gins(AFLD1, Z, Z); 8243e12c5d1SDavid du Colombier if(v < 0) 8253e12c5d1SDavid du Colombier fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0); 8263e12c5d1SDavid du Colombier else 8273e12c5d1SDavid du Colombier fgopcode(OADD, &fregnode0, &fregnode1, 1, 0); 8283e12c5d1SDavid du Colombier if(nn != Z && (o == OPREINC || o == OPREDEC)) 8293e12c5d1SDavid du Colombier gins(AFMOVD, &fregnode0, &fregnode0); 8303e12c5d1SDavid du Colombier gmove(&fregnode0, &nod); 8317dd7cddfSDavid du Colombier if(hardleft) 8323e12c5d1SDavid du Colombier regfree(&nod); 8333e12c5d1SDavid du Colombier break; 8343e12c5d1SDavid du Colombier 8353e12c5d1SDavid du Colombier bitinc: 8363e12c5d1SDavid du Colombier if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 8373e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, Z); 8383e12c5d1SDavid du Colombier gmove(&nod, nn); 8397dd7cddfSDavid du Colombier gopcode(OADD, tfield, nodconst(v), &nod); 8403e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, Z); 8413e12c5d1SDavid du Colombier break; 8423e12c5d1SDavid du Colombier } 8433e12c5d1SDavid du Colombier bitload(l, &nod, &nod1, &nod2, nn); 8447dd7cddfSDavid du Colombier gopcode(OADD, tfield, nodconst(v), &nod); 8453e12c5d1SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn); 8463e12c5d1SDavid du Colombier break; 8473e12c5d1SDavid du Colombier } 8483e12c5d1SDavid du Colombier cursafe = curs; 8493e12c5d1SDavid du Colombier } 8503e12c5d1SDavid du Colombier 8513e12c5d1SDavid du Colombier void 8523e12c5d1SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn) 8533e12c5d1SDavid du Colombier { 8543e12c5d1SDavid du Colombier Node *r; 8553e12c5d1SDavid du Colombier long v; 8563e12c5d1SDavid du Colombier 8573e12c5d1SDavid du Colombier regialloc(t, n, nn); 8583e12c5d1SDavid du Colombier if(n->op == OIND) { 8593e12c5d1SDavid du Colombier r = n->left; 8603e12c5d1SDavid du Colombier while(r->op == OADD) 8613e12c5d1SDavid du Colombier r = r->right; 8623e12c5d1SDavid du Colombier if(sconst(r)) { 863219b2ee8SDavid du Colombier v = r->vconst; 864219b2ee8SDavid du Colombier r->vconst = 0; 8653e12c5d1SDavid du Colombier lcgen(n, t); 866219b2ee8SDavid du Colombier t->xoffset += v; 867219b2ee8SDavid du Colombier r->vconst = v; 8683e12c5d1SDavid du Colombier regind(t, n); 8693e12c5d1SDavid du Colombier return; 8703e12c5d1SDavid du Colombier } 8713e12c5d1SDavid du Colombier } 8723e12c5d1SDavid du Colombier lcgen(n, t); 8733e12c5d1SDavid du Colombier regind(t, n); 8743e12c5d1SDavid du Colombier } 8753e12c5d1SDavid du Colombier 8763e12c5d1SDavid du Colombier void 8773e12c5d1SDavid du Colombier lcgen(Node *n, Node *nn) 8783e12c5d1SDavid du Colombier { 8793e12c5d1SDavid du Colombier Prog *p1; 8803e12c5d1SDavid du Colombier Node nod; 8813e12c5d1SDavid du Colombier 8823e12c5d1SDavid du Colombier if(debug['g']) { 8833e12c5d1SDavid du Colombier prtree(nn, "lcgen lhs"); 8843e12c5d1SDavid du Colombier prtree(n, "lcgen"); 8853e12c5d1SDavid du Colombier } 8863e12c5d1SDavid du Colombier if(n == Z || n->type == T) 8873e12c5d1SDavid du Colombier return; 8883e12c5d1SDavid du Colombier if(nn == Z) { 8893e12c5d1SDavid du Colombier nn = &nod; 8903e12c5d1SDavid du Colombier regalloc(&nod, n, Z); 8913e12c5d1SDavid du Colombier } 8923e12c5d1SDavid du Colombier switch(n->op) { 8933e12c5d1SDavid du Colombier default: 8943e12c5d1SDavid du Colombier if(n->addable < INDEXED) { 8953e12c5d1SDavid du Colombier diag(n, "unknown op in lcgen: %O", n->op); 8963e12c5d1SDavid du Colombier break; 8973e12c5d1SDavid du Colombier } 8983e12c5d1SDavid du Colombier gopcode(OADDR, n->type, n, nn); 8993e12c5d1SDavid du Colombier break; 9003e12c5d1SDavid du Colombier 9013e12c5d1SDavid du Colombier case OCOMMA: 9023e12c5d1SDavid du Colombier cgen(n->left, n->left); 9033e12c5d1SDavid du Colombier lcgen(n->right, nn); 9043e12c5d1SDavid du Colombier break; 9053e12c5d1SDavid du Colombier 9063e12c5d1SDavid du Colombier case OIND: 9073e12c5d1SDavid du Colombier cgen(n->left, nn); 9083e12c5d1SDavid du Colombier break; 9093e12c5d1SDavid du Colombier 9103e12c5d1SDavid du Colombier case OCOND: 9113e12c5d1SDavid du Colombier bcgen(n->left, 1); 9123e12c5d1SDavid du Colombier p1 = p; 9133e12c5d1SDavid du Colombier lcgen(n->right->left, nn); 9143e12c5d1SDavid du Colombier gbranch(OGOTO); 9153e12c5d1SDavid du Colombier patch(p1, pc); 9163e12c5d1SDavid du Colombier p1 = p; 9173e12c5d1SDavid du Colombier lcgen(n->right->right, nn); 9183e12c5d1SDavid du Colombier patch(p1, pc); 9193e12c5d1SDavid du Colombier break; 9203e12c5d1SDavid du Colombier } 9213e12c5d1SDavid du Colombier } 9223e12c5d1SDavid du Colombier 9233e12c5d1SDavid du Colombier void 9243e12c5d1SDavid du Colombier bcgen(Node *n, int true) 9253e12c5d1SDavid du Colombier { 9263e12c5d1SDavid du Colombier 9273e12c5d1SDavid du Colombier if(n->type == T) 9283e12c5d1SDavid du Colombier gbranch(OGOTO); 9293e12c5d1SDavid du Colombier else 9303e12c5d1SDavid du Colombier boolgen(n, true, Z); 9313e12c5d1SDavid du Colombier } 9323e12c5d1SDavid du Colombier 9333e12c5d1SDavid du Colombier void 9343e12c5d1SDavid du Colombier boolgen(Node *n, int true, Node *nn) 9353e12c5d1SDavid du Colombier { 9363e12c5d1SDavid du Colombier int o; 9373e12c5d1SDavid du Colombier Prog *p1, *p2; 9383e12c5d1SDavid du Colombier Node *l, *r, nod, nod1; 9393e12c5d1SDavid du Colombier long curs; 9403e12c5d1SDavid du Colombier 9413e12c5d1SDavid du Colombier if(debug['g']) { 9423e12c5d1SDavid du Colombier prtree(nn, "boolgen lhs"); 9433e12c5d1SDavid du Colombier prtree(n, "boolgen"); 9443e12c5d1SDavid du Colombier } 9453e12c5d1SDavid du Colombier curs = cursafe; 9463e12c5d1SDavid du Colombier l = n->left; 9473e12c5d1SDavid du Colombier r = n->right; 9483e12c5d1SDavid du Colombier switch(n->op) { 9493e12c5d1SDavid du Colombier 9503e12c5d1SDavid du Colombier default: 9513e12c5d1SDavid du Colombier o = ONE; 9523e12c5d1SDavid du Colombier if(true) 9533e12c5d1SDavid du Colombier o = OEQ; 954219b2ee8SDavid du Colombier if(typefd[n->type->etype]) { 9553e12c5d1SDavid du Colombier if(n->addable < INDEXED) { 9563e12c5d1SDavid du Colombier cgen(n, &fregnode0); 9573e12c5d1SDavid du Colombier gins(AFLDZ, Z, Z); 9583e12c5d1SDavid du Colombier fgopcode(o, &fregnode0, &fregnode1, 1, 1); 9593e12c5d1SDavid du Colombier } else { 9603e12c5d1SDavid du Colombier gins(AFLDZ, Z, Z); 9613e12c5d1SDavid du Colombier fgopcode(o, n, &fregnode0, 0, 1); 9623e12c5d1SDavid du Colombier } 9633e12c5d1SDavid du Colombier goto com; 9643e12c5d1SDavid du Colombier } 965219b2ee8SDavid du Colombier /* bad, 13 is address of external that becomes constant */ 966219b2ee8SDavid du Colombier if(n->addable >= INDEXED && n->addable != 13) { 9673e12c5d1SDavid du Colombier gopcode(o, n->type, n, nodconst(0)); 9683e12c5d1SDavid du Colombier goto com; 9693e12c5d1SDavid du Colombier } 9703e12c5d1SDavid du Colombier regalloc(&nod, n, nn); 9713e12c5d1SDavid du Colombier cgen(n, &nod); 9723e12c5d1SDavid du Colombier gopcode(o, n->type, &nod, nodconst(0)); 9733e12c5d1SDavid du Colombier regfree(&nod); 9743e12c5d1SDavid du Colombier goto com; 9753e12c5d1SDavid du Colombier 9763e12c5d1SDavid du Colombier case OCONST: 9773e12c5d1SDavid du Colombier o = vconst(n); 9783e12c5d1SDavid du Colombier if(!true) 9793e12c5d1SDavid du Colombier o = !o; 9803e12c5d1SDavid du Colombier gbranch(OGOTO); 9813e12c5d1SDavid du Colombier if(o) { 9823e12c5d1SDavid du Colombier p1 = p; 9833e12c5d1SDavid du Colombier gbranch(OGOTO); 9843e12c5d1SDavid du Colombier patch(p1, pc); 9853e12c5d1SDavid du Colombier } 9863e12c5d1SDavid du Colombier goto com; 9873e12c5d1SDavid du Colombier 9883e12c5d1SDavid du Colombier case OCOMMA: 9893e12c5d1SDavid du Colombier cgen(l, Z); 9903e12c5d1SDavid du Colombier boolgen(r, true, nn); 9913e12c5d1SDavid du Colombier break; 9923e12c5d1SDavid du Colombier 9933e12c5d1SDavid du Colombier case ONOT: 9943e12c5d1SDavid du Colombier boolgen(l, !true, nn); 9953e12c5d1SDavid du Colombier break; 9963e12c5d1SDavid du Colombier 9973e12c5d1SDavid du Colombier case OCOND: 9983e12c5d1SDavid du Colombier bcgen(l, 1); 9993e12c5d1SDavid du Colombier p1 = p; 10003e12c5d1SDavid du Colombier bcgen(r->left, true); 10013e12c5d1SDavid du Colombier p2 = p; 10023e12c5d1SDavid du Colombier gbranch(OGOTO); 10033e12c5d1SDavid du Colombier patch(p1, pc); 10043e12c5d1SDavid du Colombier p1 = p; 10053e12c5d1SDavid du Colombier bcgen(r->right, !true); 10063e12c5d1SDavid du Colombier patch(p2, pc); 10073e12c5d1SDavid du Colombier p2 = p; 10083e12c5d1SDavid du Colombier gbranch(OGOTO); 10093e12c5d1SDavid du Colombier patch(p1, pc); 10103e12c5d1SDavid du Colombier patch(p2, pc); 10113e12c5d1SDavid du Colombier goto com; 10123e12c5d1SDavid du Colombier 10133e12c5d1SDavid du Colombier case OANDAND: 10143e12c5d1SDavid du Colombier if(!true) 10153e12c5d1SDavid du Colombier goto caseor; 10163e12c5d1SDavid du Colombier 10173e12c5d1SDavid du Colombier caseand: 10183e12c5d1SDavid du Colombier bcgen(l, true); 10193e12c5d1SDavid du Colombier p1 = p; 10203e12c5d1SDavid du Colombier bcgen(r, !true); 10213e12c5d1SDavid du Colombier p2 = p; 10223e12c5d1SDavid du Colombier patch(p1, pc); 10233e12c5d1SDavid du Colombier gbranch(OGOTO); 10243e12c5d1SDavid du Colombier patch(p2, pc); 10253e12c5d1SDavid du Colombier goto com; 10263e12c5d1SDavid du Colombier 10273e12c5d1SDavid du Colombier case OOROR: 10283e12c5d1SDavid du Colombier if(!true) 10293e12c5d1SDavid du Colombier goto caseand; 10303e12c5d1SDavid du Colombier 10313e12c5d1SDavid du Colombier caseor: 10323e12c5d1SDavid du Colombier bcgen(l, !true); 10333e12c5d1SDavid du Colombier p1 = p; 10343e12c5d1SDavid du Colombier bcgen(r, !true); 10353e12c5d1SDavid du Colombier p2 = p; 10363e12c5d1SDavid du Colombier gbranch(OGOTO); 10373e12c5d1SDavid du Colombier patch(p1, pc); 10383e12c5d1SDavid du Colombier patch(p2, pc); 10393e12c5d1SDavid du Colombier goto com; 10403e12c5d1SDavid du Colombier 10413e12c5d1SDavid du Colombier case OEQ: 10423e12c5d1SDavid du Colombier case ONE: 10433e12c5d1SDavid du Colombier case OLE: 10443e12c5d1SDavid du Colombier case OLT: 10453e12c5d1SDavid du Colombier case OGE: 10463e12c5d1SDavid du Colombier case OGT: 10473e12c5d1SDavid du Colombier case OHI: 10483e12c5d1SDavid du Colombier case OHS: 10493e12c5d1SDavid du Colombier case OLO: 10503e12c5d1SDavid du Colombier case OLS: 10513e12c5d1SDavid du Colombier o = n->op; 10523e12c5d1SDavid du Colombier if(true) 10533e12c5d1SDavid du Colombier o = comrel[relindex(o)]; 10543e12c5d1SDavid du Colombier if(l->complex >= FNX && r->complex >= FNX) { 10553e12c5d1SDavid du Colombier regret(&nod, r); 10563e12c5d1SDavid du Colombier cgen(r, &nod); 10573e12c5d1SDavid du Colombier regsalloc(&nod1, r); 10583e12c5d1SDavid du Colombier gmove(&nod, &nod1); 10593e12c5d1SDavid du Colombier regfree(&nod); 10603e12c5d1SDavid du Colombier nod = *n; 10613e12c5d1SDavid du Colombier nod.right = &nod1; 10623e12c5d1SDavid du Colombier boolgen(&nod, true, nn); 10633e12c5d1SDavid du Colombier break; 10643e12c5d1SDavid du Colombier } 1065219b2ee8SDavid du Colombier if(typefd[l->type->etype]) { 10663e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 10673e12c5d1SDavid du Colombier cgen(l, &fregnode0); 10683e12c5d1SDavid du Colombier if(r->addable < INDEXED) { 10693e12c5d1SDavid du Colombier cgen(r, &fregnode0); 10703e12c5d1SDavid du Colombier o = invrel[relindex(o)]; 10713e12c5d1SDavid du Colombier fgopcode(o, &fregnode0, &fregnode1, 1, 1); 10723e12c5d1SDavid du Colombier } else 10733e12c5d1SDavid du Colombier fgopcode(o, r, &fregnode0, 0, 1); 10743e12c5d1SDavid du Colombier } else { 10753e12c5d1SDavid du Colombier o = invrel[relindex(o)]; 10763e12c5d1SDavid du Colombier cgen(r, &fregnode0); 10773e12c5d1SDavid du Colombier if(l->addable < INDEXED) { 10783e12c5d1SDavid du Colombier cgen(l, &fregnode0); 10793e12c5d1SDavid du Colombier o = invrel[relindex(o)]; 10803e12c5d1SDavid du Colombier fgopcode(o, &fregnode0, &fregnode1, 1, 1); 10813e12c5d1SDavid du Colombier } else 10823e12c5d1SDavid du Colombier fgopcode(o, l, &fregnode0, 0, 1); 10833e12c5d1SDavid du Colombier } 10843e12c5d1SDavid du Colombier goto com; 10853e12c5d1SDavid du Colombier } 10863e12c5d1SDavid du Colombier if(l->op == OCONST) { 10873e12c5d1SDavid du Colombier o = invrel[relindex(o)]; 10883e12c5d1SDavid du Colombier /* bad, 13 is address of external that becomes constant */ 10893e12c5d1SDavid du Colombier if(r->addable < INDEXED || r->addable == 13) { 10903e12c5d1SDavid du Colombier regalloc(&nod, r, nn); 10913e12c5d1SDavid du Colombier cgen(r, &nod); 10923e12c5d1SDavid du Colombier gopcode(o, l->type, &nod, l); 10933e12c5d1SDavid du Colombier regfree(&nod); 10943e12c5d1SDavid du Colombier } else 10953e12c5d1SDavid du Colombier gopcode(o, l->type, r, l); 10963e12c5d1SDavid du Colombier goto com; 10973e12c5d1SDavid du Colombier } 10983e12c5d1SDavid du Colombier if(l->complex >= r->complex) { 10993e12c5d1SDavid du Colombier regalloc(&nod, l, nn); 11003e12c5d1SDavid du Colombier cgen(l, &nod); 11013e12c5d1SDavid du Colombier if(r->addable < INDEXED) { 11023e12c5d1SDavid du Colombier regalloc(&nod1, r, Z); 11033e12c5d1SDavid du Colombier cgen(r, &nod1); 11043e12c5d1SDavid du Colombier gopcode(o, l->type, &nod, &nod1); 11053e12c5d1SDavid du Colombier regfree(&nod1); 11063e12c5d1SDavid du Colombier } else 11073e12c5d1SDavid du Colombier gopcode(o, l->type, &nod, r); 11083e12c5d1SDavid du Colombier regfree(&nod); 11093e12c5d1SDavid du Colombier goto com; 11103e12c5d1SDavid du Colombier } 11113e12c5d1SDavid du Colombier regalloc(&nod, r, nn); 11123e12c5d1SDavid du Colombier cgen(r, &nod); 11133e12c5d1SDavid du Colombier if(l->addable < INDEXED || l->addable == 13) { 11143e12c5d1SDavid du Colombier regalloc(&nod1, l, Z); 11153e12c5d1SDavid du Colombier cgen(l, &nod1); 11163e12c5d1SDavid du Colombier gopcode(o, l->type, &nod1, &nod); 11173e12c5d1SDavid du Colombier regfree(&nod1); 11183e12c5d1SDavid du Colombier } else 11193e12c5d1SDavid du Colombier gopcode(o, l->type, l, &nod); 11203e12c5d1SDavid du Colombier regfree(&nod); 11213e12c5d1SDavid du Colombier 11223e12c5d1SDavid du Colombier com: 11233e12c5d1SDavid du Colombier if(nn != Z) { 11243e12c5d1SDavid du Colombier p1 = p; 11253e12c5d1SDavid du Colombier gmove(nodconst(1L), nn); 11263e12c5d1SDavid du Colombier gbranch(OGOTO); 11273e12c5d1SDavid du Colombier p2 = p; 11283e12c5d1SDavid du Colombier patch(p1, pc); 11293e12c5d1SDavid du Colombier gmove(nodconst(0L), nn); 11303e12c5d1SDavid du Colombier patch(p2, pc); 11313e12c5d1SDavid du Colombier } 11323e12c5d1SDavid du Colombier break; 11333e12c5d1SDavid du Colombier } 11343e12c5d1SDavid du Colombier cursafe = curs; 11353e12c5d1SDavid du Colombier } 11363e12c5d1SDavid du Colombier 11373e12c5d1SDavid du Colombier void 11383e12c5d1SDavid du Colombier sugen(Node *n, Node *nn, long w) 11393e12c5d1SDavid du Colombier { 11403e12c5d1SDavid du Colombier Prog *p1; 11413e12c5d1SDavid du Colombier Node nod0, nod1, nod2, nod3, nod4, *l, *r; 11423e12c5d1SDavid du Colombier Type *t; 11433e12c5d1SDavid du Colombier int c; 11443e12c5d1SDavid du Colombier 11453e12c5d1SDavid du Colombier if(n == Z || n->type == T) 11463e12c5d1SDavid du Colombier return; 11473e12c5d1SDavid du Colombier if(debug['g']) { 11483e12c5d1SDavid du Colombier prtree(nn, "sugen lhs"); 11493e12c5d1SDavid du Colombier prtree(n, "sugen"); 11503e12c5d1SDavid du Colombier } 11513e12c5d1SDavid du Colombier if(nn == nodrat) 11523e12c5d1SDavid du Colombier if(w > nrathole) 11533e12c5d1SDavid du Colombier nrathole = w; 11543e12c5d1SDavid du Colombier switch(n->op) { 11553e12c5d1SDavid du Colombier case OIND: 11563e12c5d1SDavid du Colombier if(nn == Z) { 11573e12c5d1SDavid du Colombier nullwarn(n->left, Z); 11583e12c5d1SDavid du Colombier break; 11593e12c5d1SDavid du Colombier } 11603e12c5d1SDavid du Colombier 11613e12c5d1SDavid du Colombier default: 11623e12c5d1SDavid du Colombier goto copy; 11633e12c5d1SDavid du Colombier 1164219b2ee8SDavid du Colombier case OCONST: 1165219b2ee8SDavid du Colombier if(n->type && typev[n->type->etype]) { 1166219b2ee8SDavid du Colombier if(nn == Z) { 1167219b2ee8SDavid du Colombier nullwarn(n->left, Z); 1168219b2ee8SDavid du Colombier break; 1169219b2ee8SDavid du Colombier } 1170219b2ee8SDavid du Colombier 1171*80ee5cbfSDavid du Colombier switch(nn->op) { 1172*80ee5cbfSDavid du Colombier default: 1173219b2ee8SDavid du Colombier t = nn->type; 1174219b2ee8SDavid du Colombier nn->type = types[TLONG]; 1175219b2ee8SDavid du Colombier reglcgen(&nod1, nn, Z); 1176219b2ee8SDavid du Colombier nn->type = t; 1177219b2ee8SDavid du Colombier 1178*80ee5cbfSDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 1179*80ee5cbfSDavid du Colombier gmove(nodconst((long)(n->vconst>>32)), &nod1); 1180*80ee5cbfSDavid du Colombier else 1181219b2ee8SDavid du Colombier gmove(nodconst((long)(n->vconst)), &nod1); 1182219b2ee8SDavid du Colombier nod1.xoffset += SZ_LONG; 1183*80ee5cbfSDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 1184*80ee5cbfSDavid du Colombier gmove(nodconst((long)(n->vconst)), &nod1); 1185*80ee5cbfSDavid du Colombier else 1186219b2ee8SDavid du Colombier gmove(nodconst((long)(n->vconst>>32)), &nod1); 1187219b2ee8SDavid du Colombier 1188219b2ee8SDavid du Colombier regfree(&nod1); 1189219b2ee8SDavid du Colombier break; 1190*80ee5cbfSDavid du Colombier 1191*80ee5cbfSDavid du Colombier case ONAME: 1192*80ee5cbfSDavid du Colombier case OINDREG: 1193*80ee5cbfSDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 1194*80ee5cbfSDavid du Colombier gins(AMOVL, nodconst((long)(n->vconst>>32)), nn); 1195*80ee5cbfSDavid du Colombier else 1196*80ee5cbfSDavid du Colombier gins(AMOVL, nodconst((long)(n->vconst)), nn); 1197*80ee5cbfSDavid du Colombier nn->xoffset += SZ_LONG; 1198*80ee5cbfSDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 1199*80ee5cbfSDavid du Colombier gins(AMOVL, nodconst((long)(n->vconst)), nn); 1200*80ee5cbfSDavid du Colombier else 1201*80ee5cbfSDavid du Colombier gins(AMOVL, nodconst((long)(n->vconst>>32)), nn); 1202*80ee5cbfSDavid du Colombier nn->xoffset -= SZ_LONG; 1203*80ee5cbfSDavid du Colombier break; 1204*80ee5cbfSDavid du Colombier } 1205*80ee5cbfSDavid du Colombier break; 1206219b2ee8SDavid du Colombier } 1207219b2ee8SDavid du Colombier goto copy; 1208219b2ee8SDavid du Colombier 12093e12c5d1SDavid du Colombier case ODOT: 12103e12c5d1SDavid du Colombier l = n->left; 12113e12c5d1SDavid du Colombier sugen(l, nodrat, l->type->width); 12127dd7cddfSDavid du Colombier if(nn == Z) 12137dd7cddfSDavid du Colombier break; 12143e12c5d1SDavid du Colombier warn(n, "non-interruptable temporary"); 12153e12c5d1SDavid du Colombier nod1 = *nodrat; 12163e12c5d1SDavid du Colombier r = n->right; 12173e12c5d1SDavid du Colombier if(!r || r->op != OCONST) { 12183e12c5d1SDavid du Colombier diag(n, "DOT and no offset"); 12193e12c5d1SDavid du Colombier break; 12203e12c5d1SDavid du Colombier } 1221219b2ee8SDavid du Colombier nod1.xoffset += (long)r->vconst; 12223e12c5d1SDavid du Colombier nod1.type = n->type; 12233e12c5d1SDavid du Colombier sugen(&nod1, nn, w); 12243e12c5d1SDavid du Colombier break; 12253e12c5d1SDavid du Colombier 12263e12c5d1SDavid du Colombier case OSTRUCT: 1227219b2ee8SDavid du Colombier /* 1228219b2ee8SDavid du Colombier * rewrite so lhs has no fn call 1229219b2ee8SDavid du Colombier */ 1230*80ee5cbfSDavid du Colombier if(nn != Z && side(nn)) { 1231219b2ee8SDavid du Colombier nod1 = *n; 1232219b2ee8SDavid du Colombier nod1.type = typ(TIND, n->type); 1233219b2ee8SDavid du Colombier regret(&nod2, &nod1); 1234219b2ee8SDavid du Colombier lcgen(nn, &nod2); 1235219b2ee8SDavid du Colombier regsalloc(&nod0, &nod1); 1236219b2ee8SDavid du Colombier cgen(&nod2, &nod0); 1237219b2ee8SDavid du Colombier regfree(&nod2); 1238219b2ee8SDavid du Colombier 1239219b2ee8SDavid du Colombier nod1 = *n; 1240219b2ee8SDavid du Colombier nod1.op = OIND; 1241219b2ee8SDavid du Colombier nod1.left = &nod0; 1242219b2ee8SDavid du Colombier nod1.right = Z; 1243219b2ee8SDavid du Colombier nod1.complex = 1; 1244219b2ee8SDavid du Colombier 1245219b2ee8SDavid du Colombier sugen(n, &nod1, w); 1246219b2ee8SDavid du Colombier return; 1247219b2ee8SDavid du Colombier } 1248219b2ee8SDavid du Colombier 12493e12c5d1SDavid du Colombier r = n->left; 12503e12c5d1SDavid du Colombier for(t = n->type->link; t != T; t = t->down) { 12513e12c5d1SDavid du Colombier l = r; 12523e12c5d1SDavid du Colombier if(r->op == OLIST) { 12533e12c5d1SDavid du Colombier l = r->left; 12543e12c5d1SDavid du Colombier r = r->right; 12553e12c5d1SDavid du Colombier } 12563e12c5d1SDavid du Colombier if(nn == Z) { 12573e12c5d1SDavid du Colombier cgen(l, nn); 12583e12c5d1SDavid du Colombier continue; 12593e12c5d1SDavid du Colombier } 12603e12c5d1SDavid du Colombier /* 12613e12c5d1SDavid du Colombier * hand craft *(&nn + o) = l 12623e12c5d1SDavid du Colombier */ 12633e12c5d1SDavid du Colombier nod0 = znode; 12643e12c5d1SDavid du Colombier nod0.op = OAS; 12653e12c5d1SDavid du Colombier nod0.type = t; 12663e12c5d1SDavid du Colombier nod0.left = &nod1; 1267*80ee5cbfSDavid du Colombier nod0.right = nil; 12683e12c5d1SDavid du Colombier 12693e12c5d1SDavid du Colombier nod1 = znode; 12703e12c5d1SDavid du Colombier nod1.op = OIND; 12713e12c5d1SDavid du Colombier nod1.type = t; 12723e12c5d1SDavid du Colombier nod1.left = &nod2; 12733e12c5d1SDavid du Colombier 12743e12c5d1SDavid du Colombier nod2 = znode; 12753e12c5d1SDavid du Colombier nod2.op = OADD; 12763e12c5d1SDavid du Colombier nod2.type = typ(TIND, t); 12773e12c5d1SDavid du Colombier nod2.left = &nod3; 12783e12c5d1SDavid du Colombier nod2.right = &nod4; 12793e12c5d1SDavid du Colombier 12803e12c5d1SDavid du Colombier nod3 = znode; 12813e12c5d1SDavid du Colombier nod3.op = OADDR; 12823e12c5d1SDavid du Colombier nod3.type = nod2.type; 12833e12c5d1SDavid du Colombier nod3.left = nn; 12843e12c5d1SDavid du Colombier 12853e12c5d1SDavid du Colombier nod4 = znode; 12863e12c5d1SDavid du Colombier nod4.op = OCONST; 12873e12c5d1SDavid du Colombier nod4.type = nod2.type; 1288219b2ee8SDavid du Colombier nod4.vconst = t->offset; 12893e12c5d1SDavid du Colombier 12903e12c5d1SDavid du Colombier ccom(&nod0); 12913e12c5d1SDavid du Colombier acom(&nod0); 12923e12c5d1SDavid du Colombier xcom(&nod0); 12933e12c5d1SDavid du Colombier nod0.addable = 0; 12943e12c5d1SDavid du Colombier nod0.right = l; 12953e12c5d1SDavid du Colombier 12963e12c5d1SDavid du Colombier /* prtree(&nod0, "hand craft"); /* */ 12973e12c5d1SDavid du Colombier cgen(&nod0, Z); 12983e12c5d1SDavid du Colombier } 12993e12c5d1SDavid du Colombier break; 13003e12c5d1SDavid du Colombier 13013e12c5d1SDavid du Colombier case OAS: 13023e12c5d1SDavid du Colombier if(nn == Z) { 13033e12c5d1SDavid du Colombier if(n->addable < INDEXED) 13043e12c5d1SDavid du Colombier sugen(n->right, n->left, w); 13053e12c5d1SDavid du Colombier break; 13063e12c5d1SDavid du Colombier } 13077dd7cddfSDavid du Colombier 13083e12c5d1SDavid du Colombier sugen(n->right, nodrat, w); 13093e12c5d1SDavid du Colombier warn(n, "non-interruptable temporary"); 13103e12c5d1SDavid du Colombier sugen(nodrat, n->left, w); 13113e12c5d1SDavid du Colombier sugen(nodrat, nn, w); 13123e12c5d1SDavid du Colombier break; 13133e12c5d1SDavid du Colombier 13143e12c5d1SDavid du Colombier case OFUNC: 13153e12c5d1SDavid du Colombier if(nn == Z) { 13163e12c5d1SDavid du Colombier sugen(n, nodrat, w); 13173e12c5d1SDavid du Colombier break; 13183e12c5d1SDavid du Colombier } 13193e12c5d1SDavid du Colombier if(nn->op != OIND) { 13203e12c5d1SDavid du Colombier nn = new1(OADDR, nn, Z); 13213e12c5d1SDavid du Colombier nn->type = types[TIND]; 13223e12c5d1SDavid du Colombier nn->addable = 0; 13233e12c5d1SDavid du Colombier } else 13243e12c5d1SDavid du Colombier nn = nn->left; 13253e12c5d1SDavid du Colombier n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 13263e12c5d1SDavid du Colombier n->type = types[TVOID]; 13273e12c5d1SDavid du Colombier n->left->type = types[TVOID]; 13283e12c5d1SDavid du Colombier cgen(n, Z); 13293e12c5d1SDavid du Colombier break; 13303e12c5d1SDavid du Colombier 13313e12c5d1SDavid du Colombier case OCOND: 13323e12c5d1SDavid du Colombier bcgen(n->left, 1); 13333e12c5d1SDavid du Colombier p1 = p; 13343e12c5d1SDavid du Colombier sugen(n->right->left, nn, w); 13353e12c5d1SDavid du Colombier gbranch(OGOTO); 13363e12c5d1SDavid du Colombier patch(p1, pc); 13373e12c5d1SDavid du Colombier p1 = p; 13383e12c5d1SDavid du Colombier sugen(n->right->right, nn, w); 13393e12c5d1SDavid du Colombier patch(p1, pc); 13403e12c5d1SDavid du Colombier break; 13413e12c5d1SDavid du Colombier 13423e12c5d1SDavid du Colombier case OCOMMA: 13433e12c5d1SDavid du Colombier cgen(n->left, Z); 13443e12c5d1SDavid du Colombier sugen(n->right, nn, w); 13453e12c5d1SDavid du Colombier break; 13463e12c5d1SDavid du Colombier } 13473e12c5d1SDavid du Colombier return; 13483e12c5d1SDavid du Colombier 13493e12c5d1SDavid du Colombier copy: 13503e12c5d1SDavid du Colombier if(nn == Z) 13513e12c5d1SDavid du Colombier return; 13523e12c5d1SDavid du Colombier if(n->complex >= FNX && nn->complex >= FNX) { 1353219b2ee8SDavid du Colombier t = nn->type; 1354219b2ee8SDavid du Colombier nn->type = types[TLONG]; 1355219b2ee8SDavid du Colombier regialloc(&nod1, nn, Z); 1356219b2ee8SDavid du Colombier lcgen(nn, &nod1); 1357219b2ee8SDavid du Colombier regsalloc(&nod2, nn); 1358219b2ee8SDavid du Colombier nn->type = t; 1359219b2ee8SDavid du Colombier 1360219b2ee8SDavid du Colombier gins(AMOVL, &nod1, &nod2); 1361219b2ee8SDavid du Colombier regfree(&nod1); 1362219b2ee8SDavid du Colombier 1363219b2ee8SDavid du Colombier nod2.type = typ(TIND, t); 1364219b2ee8SDavid du Colombier 1365219b2ee8SDavid du Colombier nod1 = nod2; 1366219b2ee8SDavid du Colombier nod1.op = OIND; 1367219b2ee8SDavid du Colombier nod1.left = &nod2; 1368219b2ee8SDavid du Colombier nod1.right = Z; 1369219b2ee8SDavid du Colombier nod1.complex = 1; 1370219b2ee8SDavid du Colombier nod1.type = t; 1371219b2ee8SDavid du Colombier 1372219b2ee8SDavid du Colombier sugen(n, &nod1, w); 13733e12c5d1SDavid du Colombier return; 13743e12c5d1SDavid du Colombier } 13753e12c5d1SDavid du Colombier 1376*80ee5cbfSDavid du Colombier /* most common case of vlong variables */ 1377*80ee5cbfSDavid du Colombier if((n->op == ONAME || n->op == OINDREG) && 1378*80ee5cbfSDavid du Colombier (nn->op == ONAME || nn->op == OINDREG) && w == 8) { 1379*80ee5cbfSDavid du Colombier n->type = types[TLONG]; 1380*80ee5cbfSDavid du Colombier regalloc(&nod1, n, Z); 1381*80ee5cbfSDavid du Colombier gins(AMOVL, n, &nod1); 1382*80ee5cbfSDavid du Colombier gins(AMOVL, &nod1, nn); 1383*80ee5cbfSDavid du Colombier n->xoffset += SZ_LONG; 1384*80ee5cbfSDavid du Colombier nn->xoffset += SZ_LONG; 1385*80ee5cbfSDavid du Colombier gins(AMOVL, n, &nod1); 1386*80ee5cbfSDavid du Colombier gins(AMOVL, &nod1, nn); 1387*80ee5cbfSDavid du Colombier n->xoffset -= SZ_LONG; 1388*80ee5cbfSDavid du Colombier nn->xoffset -= SZ_LONG; 1389*80ee5cbfSDavid du Colombier regfree(&nod1); 1390*80ee5cbfSDavid du Colombier return; 1391*80ee5cbfSDavid du Colombier } 1392*80ee5cbfSDavid du Colombier 13933e12c5d1SDavid du Colombier /* botch, need to save in .safe */ 13943e12c5d1SDavid du Colombier c = 0; 13953e12c5d1SDavid du Colombier if(n->complex > nn->complex) { 13963e12c5d1SDavid du Colombier t = n->type; 13973e12c5d1SDavid du Colombier n->type = types[TLONG]; 13983e12c5d1SDavid du Colombier nodreg(&nod1, n, D_SI); 13993e12c5d1SDavid du Colombier if(reg[D_SI]) { 14003e12c5d1SDavid du Colombier gins(APUSHL, &nod1, Z); 14013e12c5d1SDavid du Colombier c |= 1; 14023e12c5d1SDavid du Colombier reg[D_SI]++; 14033e12c5d1SDavid du Colombier } 14043e12c5d1SDavid du Colombier lcgen(n, &nod1); 14053e12c5d1SDavid du Colombier n->type = t; 14063e12c5d1SDavid du Colombier 14073e12c5d1SDavid du Colombier t = nn->type; 14083e12c5d1SDavid du Colombier nn->type = types[TLONG]; 14093e12c5d1SDavid du Colombier nodreg(&nod2, nn, D_DI); 14103e12c5d1SDavid du Colombier if(reg[D_DI]) { 14113e12c5d1SDavid du Colombier gins(APUSHL, &nod2, Z); 14123e12c5d1SDavid du Colombier c |= 2; 14133e12c5d1SDavid du Colombier reg[D_DI]++; 14143e12c5d1SDavid du Colombier } 14153e12c5d1SDavid du Colombier lcgen(nn, &nod2); 14163e12c5d1SDavid du Colombier nn->type = t; 14173e12c5d1SDavid du Colombier } else { 14183e12c5d1SDavid du Colombier t = nn->type; 14193e12c5d1SDavid du Colombier nn->type = types[TLONG]; 14203e12c5d1SDavid du Colombier nodreg(&nod1, nn, D_DI); 14213e12c5d1SDavid du Colombier if(reg[D_DI]) { 14223e12c5d1SDavid du Colombier gins(APUSHL, &nod1, Z); 14233e12c5d1SDavid du Colombier c |= 1; 14243e12c5d1SDavid du Colombier reg[D_DI]++; 14253e12c5d1SDavid du Colombier } 14263e12c5d1SDavid du Colombier lcgen(nn, &nod1); 14273e12c5d1SDavid du Colombier nn->type = t; 14283e12c5d1SDavid du Colombier 14293e12c5d1SDavid du Colombier t = n->type; 14303e12c5d1SDavid du Colombier n->type = types[TLONG]; 14313e12c5d1SDavid du Colombier nodreg(&nod2, n, D_SI); 14323e12c5d1SDavid du Colombier if(reg[D_SI]) { 14333e12c5d1SDavid du Colombier gins(APUSHL, &nod2, Z); 14343e12c5d1SDavid du Colombier c |= 2; 14353e12c5d1SDavid du Colombier reg[D_SI]++; 14363e12c5d1SDavid du Colombier } 14373e12c5d1SDavid du Colombier lcgen(n, &nod2); 14383e12c5d1SDavid du Colombier n->type = t; 14393e12c5d1SDavid du Colombier } 14403e12c5d1SDavid du Colombier nodreg(&nod3, n, D_CX); 14413e12c5d1SDavid du Colombier if(reg[D_CX]) { 14423e12c5d1SDavid du Colombier gins(APUSHL, &nod3, Z); 14433e12c5d1SDavid du Colombier c |= 4; 14443e12c5d1SDavid du Colombier reg[D_CX]++; 14453e12c5d1SDavid du Colombier } 14463e12c5d1SDavid du Colombier gins(AMOVL, nodconst(w/SZ_LONG), &nod3); 14473e12c5d1SDavid du Colombier gins(ACLD, Z, Z); 14483e12c5d1SDavid du Colombier gins(AREP, Z, Z); 14493e12c5d1SDavid du Colombier gins(AMOVSL, Z, Z); 14503e12c5d1SDavid du Colombier if(c & 4) { 14513e12c5d1SDavid du Colombier gins(APOPL, Z, &nod3); 14523e12c5d1SDavid du Colombier reg[D_CX]--; 14533e12c5d1SDavid du Colombier } 14543e12c5d1SDavid du Colombier if(c & 2) { 14553e12c5d1SDavid du Colombier gins(APOPL, Z, &nod2); 14563e12c5d1SDavid du Colombier reg[nod2.reg]--; 14573e12c5d1SDavid du Colombier } 14583e12c5d1SDavid du Colombier if(c & 1) { 14593e12c5d1SDavid du Colombier gins(APOPL, Z, &nod1); 14603e12c5d1SDavid du Colombier reg[nod1.reg]--; 14613e12c5d1SDavid du Colombier } 14623e12c5d1SDavid du Colombier } 1463