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