17dd7cddfSDavid du Colombier #include "gc.h"
27dd7cddfSDavid du Colombier
3*6891d857SDavid du Colombier static void cmpv(Node*, int, Node*);
4*6891d857SDavid du Colombier static void testv(Node*, int);
5*6891d857SDavid du Colombier static void cgen64(Node*, Node*);
6*6891d857SDavid du Colombier static int isvconstable(int, vlong);
7*6891d857SDavid du Colombier
87dd7cddfSDavid du Colombier void
cgen(Node * n,Node * nn)97dd7cddfSDavid du Colombier cgen(Node *n, Node *nn)
107dd7cddfSDavid du Colombier {
117dd7cddfSDavid du Colombier Node *l, *r;
127dd7cddfSDavid du Colombier Prog *p1;
137dd7cddfSDavid du Colombier Node nod, nod1, nod2, nod3, nod4;
147dd7cddfSDavid du Colombier int o;
157dd7cddfSDavid du Colombier long v, curs;
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier if(debug['g']) {
187dd7cddfSDavid du Colombier prtree(nn, "cgen lhs");
197dd7cddfSDavid du Colombier prtree(n, "cgen");
207dd7cddfSDavid du Colombier }
217dd7cddfSDavid du Colombier if(n == Z || n->type == T)
227dd7cddfSDavid du Colombier return;
23*6891d857SDavid du Colombier if(typesu[n->type->etype]) {
247dd7cddfSDavid du Colombier sugen(n, nn, n->type->width);
257dd7cddfSDavid du Colombier return;
267dd7cddfSDavid du Colombier }
27*6891d857SDavid du Colombier if(typev[n->type->etype]) {
28*6891d857SDavid du Colombier switch(n->op) {
29*6891d857SDavid du Colombier case OCONST:
30*6891d857SDavid du Colombier case OFUNC:
31*6891d857SDavid du Colombier cgen64(n, nn);
32*6891d857SDavid du Colombier return;
33*6891d857SDavid du Colombier }
34*6891d857SDavid du Colombier }
357dd7cddfSDavid du Colombier l = n->left;
367dd7cddfSDavid du Colombier r = n->right;
377dd7cddfSDavid du Colombier o = n->op;
387dd7cddfSDavid du Colombier if(n->addable >= INDEXED) {
397dd7cddfSDavid du Colombier if(nn == Z) {
407dd7cddfSDavid du Colombier switch(o) {
417dd7cddfSDavid du Colombier default:
427dd7cddfSDavid du Colombier nullwarn(Z, Z);
437dd7cddfSDavid du Colombier break;
447dd7cddfSDavid du Colombier case OINDEX:
457dd7cddfSDavid du Colombier nullwarn(l, r);
467dd7cddfSDavid du Colombier break;
477dd7cddfSDavid du Colombier }
487dd7cddfSDavid du Colombier return;
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier gmove(n, nn);
517dd7cddfSDavid du Colombier return;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier curs = cursafe;
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier if(n->complex >= FNX)
567dd7cddfSDavid du Colombier if(l->complex >= FNX)
577dd7cddfSDavid du Colombier if(r != Z && r->complex >= FNX)
587dd7cddfSDavid du Colombier switch(o) {
597dd7cddfSDavid du Colombier default:
60*6891d857SDavid du Colombier if(!typev[r->type->etype]) {
617dd7cddfSDavid du Colombier regret(&nod, r);
627dd7cddfSDavid du Colombier cgen(r, &nod);
637dd7cddfSDavid du Colombier regsalloc(&nod1, r);
64*6891d857SDavid du Colombier gmove(&nod, &nod1);
657dd7cddfSDavid du Colombier regfree(&nod);
66*6891d857SDavid du Colombier } else {
67*6891d857SDavid du Colombier regsalloc(&nod1, r);
68*6891d857SDavid du Colombier cgen(r, &nod1);
69*6891d857SDavid du Colombier }
70*6891d857SDavid du Colombier
717dd7cddfSDavid du Colombier nod = *n;
727dd7cddfSDavid du Colombier nod.right = &nod1;
737dd7cddfSDavid du Colombier cgen(&nod, nn);
747dd7cddfSDavid du Colombier return;
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier case OFUNC:
777dd7cddfSDavid du Colombier case OCOMMA:
787dd7cddfSDavid du Colombier case OANDAND:
797dd7cddfSDavid du Colombier case OOROR:
807dd7cddfSDavid du Colombier case OCOND:
817dd7cddfSDavid du Colombier case ODOT:
827dd7cddfSDavid du Colombier break;
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier switch(o) {
867dd7cddfSDavid du Colombier default:
877dd7cddfSDavid du Colombier diag(n, "unknown op in cgen: %O", o);
887dd7cddfSDavid du Colombier break;
897dd7cddfSDavid du Colombier
90*6891d857SDavid du Colombier case ONEG:
91*6891d857SDavid du Colombier case OCOM:
92*6891d857SDavid du Colombier if(nn == Z) {
93*6891d857SDavid du Colombier nullwarn(l, Z);
94*6891d857SDavid du Colombier break;
95*6891d857SDavid du Colombier }
96*6891d857SDavid du Colombier regalloc(&nod, l, nn);
97*6891d857SDavid du Colombier cgen(l, &nod);
98*6891d857SDavid du Colombier gopcode(o, &nod, Z, &nod);
99*6891d857SDavid du Colombier gmove(&nod, nn);
100*6891d857SDavid du Colombier regfree(&nod);
101*6891d857SDavid du Colombier break;
102*6891d857SDavid du Colombier
1037dd7cddfSDavid du Colombier case OAS:
1047dd7cddfSDavid du Colombier if(l->op == OBIT)
1057dd7cddfSDavid du Colombier goto bitas;
1067dd7cddfSDavid du Colombier if(l->addable >= INDEXED) {
1077dd7cddfSDavid du Colombier if(nn != Z || r->addable < INDEXED) {
1087dd7cddfSDavid du Colombier regalloc(&nod, r, nn);
1097dd7cddfSDavid du Colombier cgen(r, &nod);
1107dd7cddfSDavid du Colombier gmove(&nod, l);
1117dd7cddfSDavid du Colombier regfree(&nod);
1127dd7cddfSDavid du Colombier } else
1137dd7cddfSDavid du Colombier gmove(r, l);
1147dd7cddfSDavid du Colombier break;
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier if(l->complex >= r->complex) {
1177dd7cddfSDavid du Colombier reglcgen(&nod1, l, Z);
1187dd7cddfSDavid du Colombier if(r->addable >= INDEXED) {
1197dd7cddfSDavid du Colombier gmove(r, &nod1);
1207dd7cddfSDavid du Colombier if(nn != Z)
1217dd7cddfSDavid du Colombier gmove(r, nn);
1227dd7cddfSDavid du Colombier regfree(&nod1);
1237dd7cddfSDavid du Colombier break;
1247dd7cddfSDavid du Colombier }
1257dd7cddfSDavid du Colombier regalloc(&nod, r, nn);
1267dd7cddfSDavid du Colombier cgen(r, &nod);
1277dd7cddfSDavid du Colombier } else {
1287dd7cddfSDavid du Colombier regalloc(&nod, r, nn);
1297dd7cddfSDavid du Colombier cgen(r, &nod);
1307dd7cddfSDavid du Colombier reglcgen(&nod1, l, Z);
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier gmove(&nod, &nod1);
1337dd7cddfSDavid du Colombier regfree(&nod);
1347dd7cddfSDavid du Colombier regfree(&nod1);
1357dd7cddfSDavid du Colombier break;
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier bitas:
1387dd7cddfSDavid du Colombier n = l->left;
1397dd7cddfSDavid du Colombier regalloc(&nod, r, nn);
1407dd7cddfSDavid du Colombier if(l->complex >= r->complex) {
1417dd7cddfSDavid du Colombier reglcgen(&nod1, n, Z);
1427dd7cddfSDavid du Colombier cgen(r, &nod);
1437dd7cddfSDavid du Colombier } else {
1447dd7cddfSDavid du Colombier cgen(r, &nod);
1457dd7cddfSDavid du Colombier reglcgen(&nod1, n, Z);
1467dd7cddfSDavid du Colombier }
1477dd7cddfSDavid du Colombier regalloc(&nod2, n, Z);
1487dd7cddfSDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
1497dd7cddfSDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
1507dd7cddfSDavid du Colombier break;
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier case OBIT:
1537dd7cddfSDavid du Colombier if(nn == Z) {
1547dd7cddfSDavid du Colombier nullwarn(l, Z);
1557dd7cddfSDavid du Colombier break;
1567dd7cddfSDavid du Colombier }
1577dd7cddfSDavid du Colombier bitload(n, &nod, Z, Z, nn);
1587dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, nn);
1597dd7cddfSDavid du Colombier regfree(&nod);
1607dd7cddfSDavid du Colombier break;
1617dd7cddfSDavid du Colombier
1627dd7cddfSDavid du Colombier case OXOR:
1637dd7cddfSDavid du Colombier if(nn != Z)
1647dd7cddfSDavid du Colombier if(r->op == OCONST && r->vconst == -1){
165*6891d857SDavid du Colombier regalloc(&nod, l, nn);
166*6891d857SDavid du Colombier cgen(l, &nod);
167*6891d857SDavid du Colombier gopcode(OCOM, &nod, Z, &nod);
168*6891d857SDavid du Colombier gmove(&nod, nn);
169*6891d857SDavid du Colombier regfree(&nod);
1707dd7cddfSDavid du Colombier break;
1717dd7cddfSDavid du Colombier }
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier case OADD:
1747dd7cddfSDavid du Colombier case OSUB:
1757dd7cddfSDavid du Colombier case OAND:
1767dd7cddfSDavid du Colombier case OOR:
1777dd7cddfSDavid du Colombier case OLSHR:
1787dd7cddfSDavid du Colombier case OASHL:
1797dd7cddfSDavid du Colombier case OASHR:
1807dd7cddfSDavid du Colombier /*
1817dd7cddfSDavid du Colombier * immediate operands
1827dd7cddfSDavid du Colombier */
183*6891d857SDavid du Colombier if(nn != Z && r->op == OCONST && !typefd[n->type->etype] &&
184*6891d857SDavid du Colombier (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
185*6891d857SDavid du Colombier regalloc(&nod, l, nn);
186*6891d857SDavid du Colombier cgen(l, &nod);
187*6891d857SDavid du Colombier if(o == OAND || r->vconst != 0)
188*6891d857SDavid du Colombier gopcode(o, r, Z, &nod);
189*6891d857SDavid du Colombier gmove(&nod, nn);
190*6891d857SDavid du Colombier regfree(&nod);
1917dd7cddfSDavid du Colombier break;
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier
1947dd7cddfSDavid du Colombier case OMUL:
1957dd7cddfSDavid du Colombier case OLMUL:
1967dd7cddfSDavid du Colombier case OLDIV:
1977dd7cddfSDavid du Colombier case OLMOD:
1987dd7cddfSDavid du Colombier case ODIV:
1997dd7cddfSDavid du Colombier case OMOD:
2007dd7cddfSDavid du Colombier if(nn == Z) {
2017dd7cddfSDavid du Colombier nullwarn(l, r);
2027dd7cddfSDavid du Colombier break;
2037dd7cddfSDavid du Colombier }
204*6891d857SDavid du Colombier if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) {
2057dd7cddfSDavid du Colombier if(mulcon(n, nn))
2067dd7cddfSDavid du Colombier break;
2077dd7cddfSDavid du Colombier if(debug['M'])
2087dd7cddfSDavid du Colombier print("%L multiply\n", n->lineno);
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier if(l->complex >= r->complex) {
2117dd7cddfSDavid du Colombier regalloc(&nod, l, nn);
2127dd7cddfSDavid du Colombier cgen(l, &nod);
213*6891d857SDavid du Colombier if(o != OMUL || typev[n->type->etype] || !sconst(r)) {
2147dd7cddfSDavid du Colombier regalloc(&nod1, r, Z);
2157dd7cddfSDavid du Colombier cgen(r, &nod1);
2167dd7cddfSDavid du Colombier gopcode(o, &nod1, Z, &nod);
217*6891d857SDavid du Colombier regfree(&nod1);
218*6891d857SDavid du Colombier } else
219*6891d857SDavid du Colombier gopcode(o, r, Z, &nod);
2207dd7cddfSDavid du Colombier } else {
221*6891d857SDavid du Colombier regalloc(&nod1, r, nn);
222*6891d857SDavid du Colombier cgen(r, &nod1);
223*6891d857SDavid du Colombier regalloc(&nod, l, Z);
224*6891d857SDavid du Colombier cgen(l, &nod);
225*6891d857SDavid du Colombier gopcode(o, &nod1, Z, &nod);
226*6891d857SDavid du Colombier regfree(&nod1);
2277dd7cddfSDavid du Colombier }
2287dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, nn);
2297dd7cddfSDavid du Colombier regfree(&nod);
2307dd7cddfSDavid du Colombier break;
2317dd7cddfSDavid du Colombier
2327dd7cddfSDavid du Colombier case OASLSHR:
2337dd7cddfSDavid du Colombier case OASASHL:
2347dd7cddfSDavid du Colombier case OASASHR:
2357dd7cddfSDavid du Colombier case OASAND:
2367dd7cddfSDavid du Colombier case OASADD:
2377dd7cddfSDavid du Colombier case OASSUB:
2387dd7cddfSDavid du Colombier case OASXOR:
2397dd7cddfSDavid du Colombier case OASOR:
2407dd7cddfSDavid du Colombier if(l->op == OBIT)
2417dd7cddfSDavid du Colombier goto asbitop;
242*6891d857SDavid du Colombier if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] &&
243*6891d857SDavid du Colombier (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
2447dd7cddfSDavid du Colombier if(l->addable < INDEXED)
2457dd7cddfSDavid du Colombier reglcgen(&nod2, l, Z);
2467dd7cddfSDavid du Colombier else
2477dd7cddfSDavid du Colombier nod2 = *l;
248*6891d857SDavid du Colombier regalloc(&nod, l, nn);
2497dd7cddfSDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
2507dd7cddfSDavid du Colombier gopcode(o, r, Z, &nod);
2517dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, &nod2);
2527dd7cddfSDavid du Colombier
2537dd7cddfSDavid du Colombier regfree(&nod);
2547dd7cddfSDavid du Colombier if(l->addable < INDEXED)
2557dd7cddfSDavid du Colombier regfree(&nod2);
2567dd7cddfSDavid du Colombier break;
2577dd7cddfSDavid du Colombier }
2587dd7cddfSDavid du Colombier
2597dd7cddfSDavid du Colombier case OASLMUL:
2607dd7cddfSDavid du Colombier case OASLDIV:
2617dd7cddfSDavid du Colombier case OASLMOD:
2627dd7cddfSDavid du Colombier case OASMUL:
2637dd7cddfSDavid du Colombier case OASDIV:
2647dd7cddfSDavid du Colombier case OASMOD:
2657dd7cddfSDavid du Colombier if(l->op == OBIT)
2667dd7cddfSDavid du Colombier goto asbitop;
2677dd7cddfSDavid du Colombier if(l->complex >= r->complex) {
2687dd7cddfSDavid du Colombier if(l->addable < INDEXED)
2697dd7cddfSDavid du Colombier reglcgen(&nod2, l, Z);
2707dd7cddfSDavid du Colombier else
2717dd7cddfSDavid du Colombier nod2 = *l;
272*6891d857SDavid du Colombier regalloc(&nod, r, Z);
2737dd7cddfSDavid du Colombier cgen(r, &nod);
2747dd7cddfSDavid du Colombier } else {
275*6891d857SDavid du Colombier regalloc(&nod, r, Z);
2767dd7cddfSDavid du Colombier cgen(r, &nod);
2777dd7cddfSDavid du Colombier if(l->addable < INDEXED)
2787dd7cddfSDavid du Colombier reglcgen(&nod2, l, Z);
2797dd7cddfSDavid du Colombier else
2807dd7cddfSDavid du Colombier nod2 = *l;
2817dd7cddfSDavid du Colombier }
282*6891d857SDavid du Colombier regalloc(&nod1, n, nn);
2837dd7cddfSDavid du Colombier gopcode(OAS, &nod2, Z, &nod1);
284*6891d857SDavid du Colombier gopcode(o, &nod, Z, &nod1);
285*6891d857SDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
286*6891d857SDavid du Colombier if(nn != Z)
287*6891d857SDavid du Colombier gopcode(OAS, &nod1, Z, nn);
2887dd7cddfSDavid du Colombier regfree(&nod);
2897dd7cddfSDavid du Colombier regfree(&nod1);
2907dd7cddfSDavid du Colombier if(l->addable < INDEXED)
2917dd7cddfSDavid du Colombier regfree(&nod2);
2927dd7cddfSDavid du Colombier break;
2937dd7cddfSDavid du Colombier
2947dd7cddfSDavid du Colombier asbitop:
2957dd7cddfSDavid du Colombier regalloc(&nod4, n, nn);
2967dd7cddfSDavid du Colombier regalloc(&nod3, r, Z);
2977dd7cddfSDavid du Colombier if(l->complex >= r->complex) {
2987dd7cddfSDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
2997dd7cddfSDavid du Colombier cgen(r, &nod3);
3007dd7cddfSDavid du Colombier } else {
3017dd7cddfSDavid du Colombier cgen(r, &nod3);
3027dd7cddfSDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
3037dd7cddfSDavid du Colombier }
3047dd7cddfSDavid du Colombier gmove(&nod, &nod4);
3057dd7cddfSDavid du Colombier gopcode(n->op, &nod3, Z, &nod4);
3067dd7cddfSDavid du Colombier regfree(&nod3);
3077dd7cddfSDavid du Colombier gmove(&nod4, &nod);
3087dd7cddfSDavid du Colombier regfree(&nod4);
3097dd7cddfSDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
3107dd7cddfSDavid du Colombier break;
3117dd7cddfSDavid du Colombier
3127dd7cddfSDavid du Colombier case OADDR:
3137dd7cddfSDavid du Colombier if(nn == Z) {
3147dd7cddfSDavid du Colombier nullwarn(l, Z);
3157dd7cddfSDavid du Colombier break;
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier lcgen(l, nn);
3187dd7cddfSDavid du Colombier break;
3197dd7cddfSDavid du Colombier
3207dd7cddfSDavid du Colombier case OFUNC:
3217dd7cddfSDavid du Colombier if(l->complex >= FNX) {
3227dd7cddfSDavid du Colombier if(l->op != OIND)
3237dd7cddfSDavid du Colombier diag(n, "bad function call");
3247dd7cddfSDavid du Colombier
3257dd7cddfSDavid du Colombier regret(&nod, l->left);
3267dd7cddfSDavid du Colombier cgen(l->left, &nod);
3277dd7cddfSDavid du Colombier regsalloc(&nod1, l->left);
3287dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
3297dd7cddfSDavid du Colombier regfree(&nod);
3307dd7cddfSDavid du Colombier
3317dd7cddfSDavid du Colombier nod = *n;
3327dd7cddfSDavid du Colombier nod.left = &nod2;
3337dd7cddfSDavid du Colombier nod2 = *l;
3347dd7cddfSDavid du Colombier nod2.left = &nod1;
3357dd7cddfSDavid du Colombier nod2.complex = 1;
3367dd7cddfSDavid du Colombier cgen(&nod, nn);
3377dd7cddfSDavid du Colombier
3387dd7cddfSDavid du Colombier return;
3397dd7cddfSDavid du Colombier }
3407dd7cddfSDavid du Colombier o = reg[REGARG];
3417dd7cddfSDavid du Colombier gargs(r, &nod, &nod1);
3427dd7cddfSDavid du Colombier if(l->addable < INDEXED) {
3437dd7cddfSDavid du Colombier reglcgen(&nod, l, Z);
3447dd7cddfSDavid du Colombier gopcode(OFUNC, Z, Z, &nod);
3457dd7cddfSDavid du Colombier regfree(&nod);
3467dd7cddfSDavid du Colombier } else
3477dd7cddfSDavid du Colombier gopcode(OFUNC, Z, Z, l);
3487dd7cddfSDavid du Colombier if(REGARG)
3497dd7cddfSDavid du Colombier if(o != reg[REGARG])
3507dd7cddfSDavid du Colombier reg[REGARG]--;
3517dd7cddfSDavid du Colombier if(nn != Z) {
3527dd7cddfSDavid du Colombier regret(&nod, n);
3537dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, nn);
3547dd7cddfSDavid du Colombier regfree(&nod);
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier break;
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier case OIND:
3597dd7cddfSDavid du Colombier if(nn == Z) {
3607dd7cddfSDavid du Colombier cgen(l, nn);
3617dd7cddfSDavid du Colombier break;
3627dd7cddfSDavid du Colombier }
3637dd7cddfSDavid du Colombier regialloc(&nod, n, nn);
3647dd7cddfSDavid du Colombier r = l;
3657dd7cddfSDavid du Colombier while(r->op == OADD)
3667dd7cddfSDavid du Colombier r = r->right;
3677dd7cddfSDavid du Colombier if(sconst(r)) {
3687dd7cddfSDavid du Colombier v = r->vconst;
3697dd7cddfSDavid du Colombier r->vconst = 0;
3707dd7cddfSDavid du Colombier cgen(l, &nod);
3717dd7cddfSDavid du Colombier nod.xoffset += v;
3727dd7cddfSDavid du Colombier r->vconst = v;
3737dd7cddfSDavid du Colombier } else
3747dd7cddfSDavid du Colombier cgen(l, &nod);
3757dd7cddfSDavid du Colombier regind(&nod, n);
376*6891d857SDavid du Colombier gmove(&nod, nn);
3777dd7cddfSDavid du Colombier regfree(&nod);
3787dd7cddfSDavid du Colombier break;
3797dd7cddfSDavid du Colombier
3807dd7cddfSDavid du Colombier case OEQ:
3817dd7cddfSDavid du Colombier case ONE:
3827dd7cddfSDavid du Colombier case OLE:
3837dd7cddfSDavid du Colombier case OLT:
3847dd7cddfSDavid du Colombier case OGE:
3857dd7cddfSDavid du Colombier case OGT:
3867dd7cddfSDavid du Colombier case OLO:
3877dd7cddfSDavid du Colombier case OLS:
3887dd7cddfSDavid du Colombier case OHI:
3897dd7cddfSDavid du Colombier case OHS:
3907dd7cddfSDavid du Colombier if(nn == Z) {
3917dd7cddfSDavid du Colombier nullwarn(l, r);
3927dd7cddfSDavid du Colombier break;
3937dd7cddfSDavid du Colombier }
3947dd7cddfSDavid du Colombier boolgen(n, 1, nn);
3957dd7cddfSDavid du Colombier break;
3967dd7cddfSDavid du Colombier
3977dd7cddfSDavid du Colombier case OANDAND:
3987dd7cddfSDavid du Colombier case OOROR:
3997dd7cddfSDavid du Colombier boolgen(n, 1, nn);
4007dd7cddfSDavid du Colombier if(nn == Z)
4017dd7cddfSDavid du Colombier patch(p, pc);
4027dd7cddfSDavid du Colombier break;
4037dd7cddfSDavid du Colombier
4047dd7cddfSDavid du Colombier case ONOT:
4057dd7cddfSDavid du Colombier if(nn == Z) {
4067dd7cddfSDavid du Colombier nullwarn(l, Z);
4077dd7cddfSDavid du Colombier break;
4087dd7cddfSDavid du Colombier }
4097dd7cddfSDavid du Colombier boolgen(n, 1, nn);
4107dd7cddfSDavid du Colombier break;
4117dd7cddfSDavid du Colombier
4127dd7cddfSDavid du Colombier case OCOMMA:
4137dd7cddfSDavid du Colombier cgen(l, Z);
4147dd7cddfSDavid du Colombier cgen(r, nn);
4157dd7cddfSDavid du Colombier break;
4167dd7cddfSDavid du Colombier
4177dd7cddfSDavid du Colombier case OCAST:
4187dd7cddfSDavid du Colombier if(nn == Z) {
4197dd7cddfSDavid du Colombier nullwarn(l, Z);
4207dd7cddfSDavid du Colombier break;
4217dd7cddfSDavid du Colombier }
4227dd7cddfSDavid du Colombier /*
4237dd7cddfSDavid du Colombier * convert from types l->n->nn
4247dd7cddfSDavid du Colombier */
4257dd7cddfSDavid du Colombier if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
4267dd7cddfSDavid du Colombier /* both null, gen l->nn */
4277dd7cddfSDavid du Colombier cgen(l, nn);
4287dd7cddfSDavid du Colombier break;
4297dd7cddfSDavid du Colombier }
430*6891d857SDavid du Colombier if(typev[l->type->etype] || typev[n->type->etype]) {
431*6891d857SDavid du Colombier cgen64(n, nn);
432*6891d857SDavid du Colombier break;
433*6891d857SDavid du Colombier }
4347dd7cddfSDavid du Colombier regalloc(&nod, l, nn);
4357dd7cddfSDavid du Colombier cgen(l, &nod);
4367dd7cddfSDavid du Colombier regalloc(&nod1, n, &nod);
437*6891d857SDavid du Colombier gmove(&nod, &nod1);
438*6891d857SDavid du Colombier gmove(&nod1, nn);
4397dd7cddfSDavid du Colombier regfree(&nod1);
4407dd7cddfSDavid du Colombier regfree(&nod);
4417dd7cddfSDavid du Colombier break;
4427dd7cddfSDavid du Colombier
4437dd7cddfSDavid du Colombier case ODOT:
4447dd7cddfSDavid du Colombier sugen(l, nodrat, l->type->width);
4457dd7cddfSDavid du Colombier if(nn != Z) {
4467dd7cddfSDavid du Colombier warn(n, "non-interruptable temporary");
4477dd7cddfSDavid du Colombier nod = *nodrat;
4487dd7cddfSDavid du Colombier if(!r || r->op != OCONST) {
4497dd7cddfSDavid du Colombier diag(n, "DOT and no offset");
4507dd7cddfSDavid du Colombier break;
4517dd7cddfSDavid du Colombier }
4527dd7cddfSDavid du Colombier nod.xoffset += (long)r->vconst;
4537dd7cddfSDavid du Colombier nod.type = n->type;
4547dd7cddfSDavid du Colombier cgen(&nod, nn);
4557dd7cddfSDavid du Colombier }
4567dd7cddfSDavid du Colombier break;
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier case OCOND:
4597dd7cddfSDavid du Colombier bcgen(l, 1);
4607dd7cddfSDavid du Colombier p1 = p;
4617dd7cddfSDavid du Colombier cgen(r->left, nn);
4627dd7cddfSDavid du Colombier gbranch(OGOTO);
4637dd7cddfSDavid du Colombier patch(p1, pc);
4647dd7cddfSDavid du Colombier p1 = p;
4657dd7cddfSDavid du Colombier cgen(r->right, nn);
4667dd7cddfSDavid du Colombier patch(p1, pc);
4677dd7cddfSDavid du Colombier break;
4687dd7cddfSDavid du Colombier
4697dd7cddfSDavid du Colombier case OPOSTINC:
4707dd7cddfSDavid du Colombier case OPOSTDEC:
4717dd7cddfSDavid du Colombier v = 1;
4727dd7cddfSDavid du Colombier if(l->type->etype == TIND)
4737dd7cddfSDavid du Colombier v = l->type->link->width;
4747dd7cddfSDavid du Colombier if(o == OPOSTDEC)
4757dd7cddfSDavid du Colombier v = -v;
4767dd7cddfSDavid du Colombier if(l->op == OBIT)
4777dd7cddfSDavid du Colombier goto bitinc;
4787dd7cddfSDavid du Colombier if(nn == Z)
4797dd7cddfSDavid du Colombier goto pre;
4807dd7cddfSDavid du Colombier
4817dd7cddfSDavid du Colombier if(l->addable < INDEXED)
4827dd7cddfSDavid du Colombier reglcgen(&nod2, l, Z);
4837dd7cddfSDavid du Colombier else
4847dd7cddfSDavid du Colombier nod2 = *l;
4857dd7cddfSDavid du Colombier
4867dd7cddfSDavid du Colombier regalloc(&nod, l, nn);
4877dd7cddfSDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
4887dd7cddfSDavid du Colombier regalloc(&nod1, l, Z);
4897dd7cddfSDavid du Colombier if(typefd[l->type->etype]) {
4907dd7cddfSDavid du Colombier regalloc(&nod3, l, Z);
4917dd7cddfSDavid du Colombier if(v < 0) {
4927dd7cddfSDavid du Colombier gopcode(OAS, nodfconst(-v), Z, &nod3);
4937dd7cddfSDavid du Colombier gopcode(OSUB, &nod3, &nod, &nod1);
4947dd7cddfSDavid du Colombier } else {
4957dd7cddfSDavid du Colombier gopcode(OAS, nodfconst(v), Z, &nod3);
4967dd7cddfSDavid du Colombier gopcode(OADD, &nod3, &nod, &nod1);
4977dd7cddfSDavid du Colombier }
4987dd7cddfSDavid du Colombier regfree(&nod3);
4997dd7cddfSDavid du Colombier } else
5007dd7cddfSDavid du Colombier gopcode(OADD, nodconst(v), &nod, &nod1);
5017dd7cddfSDavid du Colombier gopcode(OAS, &nod1, Z, &nod2);
5027dd7cddfSDavid du Colombier
5037dd7cddfSDavid du Colombier regfree(&nod);
5047dd7cddfSDavid du Colombier regfree(&nod1);
5057dd7cddfSDavid du Colombier if(l->addable < INDEXED)
5067dd7cddfSDavid du Colombier regfree(&nod2);
5077dd7cddfSDavid du Colombier break;
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier case OPREINC:
5107dd7cddfSDavid du Colombier case OPREDEC:
5117dd7cddfSDavid du Colombier v = 1;
5127dd7cddfSDavid du Colombier if(l->type->etype == TIND)
5137dd7cddfSDavid du Colombier v = l->type->link->width;
5147dd7cddfSDavid du Colombier if(o == OPREDEC)
5157dd7cddfSDavid du Colombier v = -v;
5167dd7cddfSDavid du Colombier if(l->op == OBIT)
5177dd7cddfSDavid du Colombier goto bitinc;
5187dd7cddfSDavid du Colombier
5197dd7cddfSDavid du Colombier pre:
5207dd7cddfSDavid du Colombier if(l->addable < INDEXED)
5217dd7cddfSDavid du Colombier reglcgen(&nod2, l, Z);
5227dd7cddfSDavid du Colombier else
5237dd7cddfSDavid du Colombier nod2 = *l;
5247dd7cddfSDavid du Colombier
5257dd7cddfSDavid du Colombier regalloc(&nod, l, nn);
5267dd7cddfSDavid du Colombier gopcode(OAS, &nod2, Z, &nod);
5277dd7cddfSDavid du Colombier if(typefd[l->type->etype]) {
5287dd7cddfSDavid du Colombier regalloc(&nod3, l, Z);
5297dd7cddfSDavid du Colombier if(v < 0) {
5307dd7cddfSDavid du Colombier gopcode(OAS, nodfconst(-v), Z, &nod3);
5317dd7cddfSDavid du Colombier gopcode(OSUB, &nod3, Z, &nod);
5327dd7cddfSDavid du Colombier } else {
5337dd7cddfSDavid du Colombier gopcode(OAS, nodfconst(v), Z, &nod3);
5347dd7cddfSDavid du Colombier gopcode(OADD, &nod3, Z, &nod);
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier regfree(&nod3);
5377dd7cddfSDavid du Colombier } else
5387dd7cddfSDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
5397dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, &nod2);
5404ac975e2SDavid du Colombier if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
5414ac975e2SDavid du Colombier gins(ANOP, l, Z);
5427dd7cddfSDavid du Colombier
5437dd7cddfSDavid du Colombier regfree(&nod);
5447dd7cddfSDavid du Colombier if(l->addable < INDEXED)
5457dd7cddfSDavid du Colombier regfree(&nod2);
5467dd7cddfSDavid du Colombier break;
5477dd7cddfSDavid du Colombier
5487dd7cddfSDavid du Colombier bitinc:
5497dd7cddfSDavid du Colombier if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
5507dd7cddfSDavid du Colombier bitload(l, &nod, &nod1, &nod2, Z);
5517dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, nn);
5527dd7cddfSDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
5537dd7cddfSDavid du Colombier bitstore(l, &nod, &nod1, &nod2, Z);
5547dd7cddfSDavid du Colombier break;
5557dd7cddfSDavid du Colombier }
5567dd7cddfSDavid du Colombier bitload(l, &nod, &nod1, &nod2, nn);
5577dd7cddfSDavid du Colombier gopcode(OADD, nodconst(v), Z, &nod);
5587dd7cddfSDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
5597dd7cddfSDavid du Colombier break;
5607dd7cddfSDavid du Colombier }
5617dd7cddfSDavid du Colombier cursafe = curs;
5627dd7cddfSDavid du Colombier }
5637dd7cddfSDavid du Colombier
5647dd7cddfSDavid du Colombier void
reglcgen(Node * t,Node * n,Node * nn)5657dd7cddfSDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
5667dd7cddfSDavid du Colombier {
5677dd7cddfSDavid du Colombier Node *r;
5687dd7cddfSDavid du Colombier long v;
5697dd7cddfSDavid du Colombier
5707dd7cddfSDavid du Colombier regialloc(t, n, nn);
5717dd7cddfSDavid du Colombier if(n->op == OIND) {
5727dd7cddfSDavid du Colombier r = n->left;
5737dd7cddfSDavid du Colombier while(r->op == OADD)
5747dd7cddfSDavid du Colombier r = r->right;
5757dd7cddfSDavid du Colombier if(sconst(r)) {
5767dd7cddfSDavid du Colombier v = r->vconst;
5777dd7cddfSDavid du Colombier r->vconst = 0;
5787dd7cddfSDavid du Colombier lcgen(n, t);
5797dd7cddfSDavid du Colombier t->xoffset += v;
5807dd7cddfSDavid du Colombier r->vconst = v;
5817dd7cddfSDavid du Colombier regind(t, n);
5827dd7cddfSDavid du Colombier return;
5837dd7cddfSDavid du Colombier }
5847dd7cddfSDavid du Colombier }
5857dd7cddfSDavid du Colombier lcgen(n, t);
5867dd7cddfSDavid du Colombier regind(t, n);
5877dd7cddfSDavid du Colombier }
5887dd7cddfSDavid du Colombier
5897dd7cddfSDavid du Colombier void
lcgen(Node * n,Node * nn)5907dd7cddfSDavid du Colombier lcgen(Node *n, Node *nn)
5917dd7cddfSDavid du Colombier {
5927dd7cddfSDavid du Colombier Prog *p1;
5937dd7cddfSDavid du Colombier Node nod;
5947dd7cddfSDavid du Colombier
5957dd7cddfSDavid du Colombier if(debug['g']) {
5967dd7cddfSDavid du Colombier prtree(nn, "lcgen lhs");
5977dd7cddfSDavid du Colombier prtree(n, "lcgen");
5987dd7cddfSDavid du Colombier }
5997dd7cddfSDavid du Colombier if(n == Z || n->type == T)
6007dd7cddfSDavid du Colombier return;
6017dd7cddfSDavid du Colombier if(nn == Z) {
6027dd7cddfSDavid du Colombier nn = &nod;
6037dd7cddfSDavid du Colombier regalloc(&nod, n, Z);
6047dd7cddfSDavid du Colombier }
6057dd7cddfSDavid du Colombier switch(n->op) {
6067dd7cddfSDavid du Colombier default:
6077dd7cddfSDavid du Colombier if(n->addable < INDEXED) {
6087dd7cddfSDavid du Colombier diag(n, "unknown op in lcgen: %O", n->op);
6097dd7cddfSDavid du Colombier break;
6107dd7cddfSDavid du Colombier }
6117dd7cddfSDavid du Colombier nod = *n;
6127dd7cddfSDavid du Colombier nod.op = OADDR;
6137dd7cddfSDavid du Colombier nod.left = n;
6147dd7cddfSDavid du Colombier nod.right = Z;
6157dd7cddfSDavid du Colombier nod.type = types[TIND];
6167dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, nn);
6177dd7cddfSDavid du Colombier break;
6187dd7cddfSDavid du Colombier
6197dd7cddfSDavid du Colombier case OCOMMA:
6207dd7cddfSDavid du Colombier cgen(n->left, n->left);
6217dd7cddfSDavid du Colombier lcgen(n->right, nn);
6227dd7cddfSDavid du Colombier break;
6237dd7cddfSDavid du Colombier
6247dd7cddfSDavid du Colombier case OIND:
6257dd7cddfSDavid du Colombier cgen(n->left, nn);
6267dd7cddfSDavid du Colombier break;
6277dd7cddfSDavid du Colombier
6287dd7cddfSDavid du Colombier case OCOND:
6297dd7cddfSDavid du Colombier bcgen(n->left, 1);
6307dd7cddfSDavid du Colombier p1 = p;
6317dd7cddfSDavid du Colombier lcgen(n->right->left, nn);
6327dd7cddfSDavid du Colombier gbranch(OGOTO);
6337dd7cddfSDavid du Colombier patch(p1, pc);
6347dd7cddfSDavid du Colombier p1 = p;
6357dd7cddfSDavid du Colombier lcgen(n->right->right, nn);
6367dd7cddfSDavid du Colombier patch(p1, pc);
6377dd7cddfSDavid du Colombier break;
6387dd7cddfSDavid du Colombier }
6397dd7cddfSDavid du Colombier }
6407dd7cddfSDavid du Colombier
6417dd7cddfSDavid du Colombier void
bcgen(Node * n,int true)6427dd7cddfSDavid du Colombier bcgen(Node *n, int true)
6437dd7cddfSDavid du Colombier {
6447dd7cddfSDavid du Colombier
6457dd7cddfSDavid du Colombier if(n->type == T)
6467dd7cddfSDavid du Colombier gbranch(OGOTO);
6477dd7cddfSDavid du Colombier else
6487dd7cddfSDavid du Colombier boolgen(n, true, Z);
6497dd7cddfSDavid du Colombier }
6507dd7cddfSDavid du Colombier
6517dd7cddfSDavid du Colombier void
boolgen(Node * n,int true,Node * nn)6527dd7cddfSDavid du Colombier boolgen(Node *n, int true, Node *nn)
6537dd7cddfSDavid du Colombier {
654*6891d857SDavid du Colombier int o, uns;
6557dd7cddfSDavid du Colombier Prog *p1, *p2;
6567dd7cddfSDavid du Colombier Node *l, *r, nod, nod1;
6577dd7cddfSDavid du Colombier long curs;
6587dd7cddfSDavid du Colombier
6597dd7cddfSDavid du Colombier if(debug['g']) {
6607dd7cddfSDavid du Colombier prtree(nn, "boolgen lhs");
6617dd7cddfSDavid du Colombier prtree(n, "boolgen");
6627dd7cddfSDavid du Colombier }
663*6891d857SDavid du Colombier uns = 0;
6647dd7cddfSDavid du Colombier curs = cursafe;
6657dd7cddfSDavid du Colombier l = n->left;
6667dd7cddfSDavid du Colombier r = n->right;
6677dd7cddfSDavid du Colombier switch(n->op) {
6687dd7cddfSDavid du Colombier
6697dd7cddfSDavid du Colombier default:
6707dd7cddfSDavid du Colombier if(n->op == OCONST) {
6717dd7cddfSDavid du Colombier o = vconst(n);
6727dd7cddfSDavid du Colombier if(!true)
6737dd7cddfSDavid du Colombier o = !o;
6747dd7cddfSDavid du Colombier gbranch(OGOTO);
6757dd7cddfSDavid du Colombier if(o) {
6767dd7cddfSDavid du Colombier p1 = p;
6777dd7cddfSDavid du Colombier gbranch(OGOTO);
6787dd7cddfSDavid du Colombier patch(p1, pc);
6797dd7cddfSDavid du Colombier }
6807dd7cddfSDavid du Colombier goto com;
6817dd7cddfSDavid du Colombier }
682*6891d857SDavid du Colombier if(typev[n->type->etype]) {
683*6891d857SDavid du Colombier testv(n, true);
684*6891d857SDavid du Colombier goto com;
685*6891d857SDavid du Colombier }
6867dd7cddfSDavid du Colombier regalloc(&nod, n, nn);
6877dd7cddfSDavid du Colombier cgen(n, &nod);
6887dd7cddfSDavid du Colombier o = ONE;
6897dd7cddfSDavid du Colombier if(true)
6907dd7cddfSDavid du Colombier o = comrel[relindex(o)];
6917dd7cddfSDavid du Colombier if(typefd[n->type->etype]) {
6927dd7cddfSDavid du Colombier nodreg(&nod1, n, NREG+FREGZERO);
6937dd7cddfSDavid du Colombier gopcode(o, &nod, Z, &nod1);
6947dd7cddfSDavid du Colombier } else
6957dd7cddfSDavid du Colombier gopcode(o, &nod, Z, nodconst(0));
6967dd7cddfSDavid du Colombier regfree(&nod);
6977dd7cddfSDavid du Colombier goto com;
6987dd7cddfSDavid du Colombier
6997dd7cddfSDavid du Colombier case OCOMMA:
7007dd7cddfSDavid du Colombier cgen(l, Z);
7017dd7cddfSDavid du Colombier boolgen(r, true, nn);
7027dd7cddfSDavid du Colombier break;
7037dd7cddfSDavid du Colombier
7047dd7cddfSDavid du Colombier case ONOT:
7057dd7cddfSDavid du Colombier boolgen(l, !true, nn);
7067dd7cddfSDavid du Colombier break;
7077dd7cddfSDavid du Colombier
7087dd7cddfSDavid du Colombier case OCOND:
7097dd7cddfSDavid du Colombier bcgen(l, 1);
7107dd7cddfSDavid du Colombier p1 = p;
7117dd7cddfSDavid du Colombier bcgen(r->left, true);
7127dd7cddfSDavid du Colombier p2 = p;
7137dd7cddfSDavid du Colombier gbranch(OGOTO);
7147dd7cddfSDavid du Colombier patch(p1, pc);
7157dd7cddfSDavid du Colombier p1 = p;
7167dd7cddfSDavid du Colombier bcgen(r->right, !true);
7177dd7cddfSDavid du Colombier patch(p2, pc);
7187dd7cddfSDavid du Colombier p2 = p;
7197dd7cddfSDavid du Colombier gbranch(OGOTO);
7207dd7cddfSDavid du Colombier patch(p1, pc);
7217dd7cddfSDavid du Colombier patch(p2, pc);
7227dd7cddfSDavid du Colombier goto com;
7237dd7cddfSDavid du Colombier
7247dd7cddfSDavid du Colombier case OANDAND:
7257dd7cddfSDavid du Colombier if(!true)
7267dd7cddfSDavid du Colombier goto caseor;
7277dd7cddfSDavid du Colombier
7287dd7cddfSDavid du Colombier caseand:
7297dd7cddfSDavid du Colombier bcgen(l, true);
7307dd7cddfSDavid du Colombier p1 = p;
7317dd7cddfSDavid du Colombier bcgen(r, !true);
7327dd7cddfSDavid du Colombier p2 = p;
7337dd7cddfSDavid du Colombier patch(p1, pc);
7347dd7cddfSDavid du Colombier gbranch(OGOTO);
7357dd7cddfSDavid du Colombier patch(p2, pc);
7367dd7cddfSDavid du Colombier goto com;
7377dd7cddfSDavid du Colombier
7387dd7cddfSDavid du Colombier case OOROR:
7397dd7cddfSDavid du Colombier if(!true)
7407dd7cddfSDavid du Colombier goto caseand;
7417dd7cddfSDavid du Colombier
7427dd7cddfSDavid du Colombier caseor:
7437dd7cddfSDavid du Colombier bcgen(l, !true);
7447dd7cddfSDavid du Colombier p1 = p;
7457dd7cddfSDavid du Colombier bcgen(r, !true);
7467dd7cddfSDavid du Colombier p2 = p;
7477dd7cddfSDavid du Colombier gbranch(OGOTO);
7487dd7cddfSDavid du Colombier patch(p1, pc);
7497dd7cddfSDavid du Colombier patch(p2, pc);
7507dd7cddfSDavid du Colombier goto com;
7517dd7cddfSDavid du Colombier
752*6891d857SDavid du Colombier case OHI:
753*6891d857SDavid du Colombier case OHS:
754*6891d857SDavid du Colombier case OLO:
755*6891d857SDavid du Colombier case OLS:
756*6891d857SDavid du Colombier uns = 1;
757*6891d857SDavid du Colombier /* fall through */
7587dd7cddfSDavid du Colombier case OEQ:
7597dd7cddfSDavid du Colombier case ONE:
7607dd7cddfSDavid du Colombier case OLE:
7617dd7cddfSDavid du Colombier case OLT:
7627dd7cddfSDavid du Colombier case OGE:
7637dd7cddfSDavid du Colombier case OGT:
764*6891d857SDavid du Colombier if(typev[l->type->etype]){
765*6891d857SDavid du Colombier cmpv(n, true, Z);
766*6891d857SDavid du Colombier goto com;
767*6891d857SDavid du Colombier }
7687dd7cddfSDavid du Colombier o = n->op;
7697dd7cddfSDavid du Colombier if(true)
7707dd7cddfSDavid du Colombier o = comrel[relindex(o)];
7717dd7cddfSDavid du Colombier if(l->complex >= FNX && r->complex >= FNX) {
7727dd7cddfSDavid du Colombier regret(&nod, r);
7737dd7cddfSDavid du Colombier cgen(r, &nod);
7747dd7cddfSDavid du Colombier regsalloc(&nod1, r);
7757dd7cddfSDavid du Colombier gopcode(OAS, &nod, Z, &nod1);
7767dd7cddfSDavid du Colombier regfree(&nod);
7777dd7cddfSDavid du Colombier nod = *n;
7787dd7cddfSDavid du Colombier nod.right = &nod1;
7797dd7cddfSDavid du Colombier boolgen(&nod, true, nn);
7807dd7cddfSDavid du Colombier break;
7817dd7cddfSDavid du Colombier }
782*6891d857SDavid du Colombier if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) {
7837dd7cddfSDavid du Colombier regalloc(&nod, l, nn);
7847dd7cddfSDavid du Colombier cgen(l, &nod);
7857dd7cddfSDavid du Colombier gopcode(o, &nod, Z, r);
7867dd7cddfSDavid du Colombier regfree(&nod);
7877dd7cddfSDavid du Colombier goto com;
7887dd7cddfSDavid du Colombier }
7897dd7cddfSDavid du Colombier if(l->complex >= r->complex) {
7907dd7cddfSDavid du Colombier regalloc(&nod1, l, nn);
7917dd7cddfSDavid du Colombier cgen(l, &nod1);
7927dd7cddfSDavid du Colombier regalloc(&nod, r, Z);
7937dd7cddfSDavid du Colombier cgen(r, &nod);
7947dd7cddfSDavid du Colombier } else {
7957dd7cddfSDavid du Colombier regalloc(&nod, r, nn);
7967dd7cddfSDavid du Colombier cgen(r, &nod);
7977dd7cddfSDavid du Colombier regalloc(&nod1, l, Z);
7987dd7cddfSDavid du Colombier cgen(l, &nod1);
7997dd7cddfSDavid du Colombier }
8007dd7cddfSDavid du Colombier gopcode(o, &nod1, Z, &nod);
8017dd7cddfSDavid du Colombier regfree(&nod);
8027dd7cddfSDavid du Colombier regfree(&nod1);
8037dd7cddfSDavid du Colombier
8047dd7cddfSDavid du Colombier com:
8057dd7cddfSDavid du Colombier if(nn != Z) {
8067dd7cddfSDavid du Colombier p1 = p;
8077dd7cddfSDavid du Colombier gopcode(OAS, nodconst(1L), Z, nn);
8087dd7cddfSDavid du Colombier gbranch(OGOTO);
8097dd7cddfSDavid du Colombier p2 = p;
8107dd7cddfSDavid du Colombier patch(p1, pc);
8117dd7cddfSDavid du Colombier gopcode(OAS, nodconst(0L), Z, nn);
8127dd7cddfSDavid du Colombier patch(p2, pc);
8137dd7cddfSDavid du Colombier }
8147dd7cddfSDavid du Colombier break;
8157dd7cddfSDavid du Colombier }
8167dd7cddfSDavid du Colombier cursafe = curs;
8177dd7cddfSDavid du Colombier }
8187dd7cddfSDavid du Colombier
8197dd7cddfSDavid du Colombier void
sugen(Node * n,Node * nn,long w)8207dd7cddfSDavid du Colombier sugen(Node *n, Node *nn, long w)
8217dd7cddfSDavid du Colombier {
8227dd7cddfSDavid du Colombier Prog *p1;
8237dd7cddfSDavid du Colombier Node nod0, nod1, nod2, nod3, nod4, *l, *r;
8247dd7cddfSDavid du Colombier Type *t;
8257dd7cddfSDavid du Colombier long pc1;
8267dd7cddfSDavid du Colombier int i, m, c;
8277dd7cddfSDavid du Colombier
8287dd7cddfSDavid du Colombier if(n == Z || n->type == T)
8297dd7cddfSDavid du Colombier return;
830*6891d857SDavid du Colombier if(nn == nodrat)
831*6891d857SDavid du Colombier if(w > nrathole)
832*6891d857SDavid du Colombier nrathole = w;
8337dd7cddfSDavid du Colombier if(debug['g']) {
8347dd7cddfSDavid du Colombier prtree(nn, "sugen lhs");
8357dd7cddfSDavid du Colombier prtree(n, "sugen");
8367dd7cddfSDavid du Colombier }
837*6891d857SDavid du Colombier if(typev[n->type->etype]) {
838*6891d857SDavid du Colombier diag(n, "old vlong sugen: %O", n->op);
839*6891d857SDavid du Colombier return;
840*6891d857SDavid du Colombier }
8417dd7cddfSDavid du Colombier switch(n->op) {
8427dd7cddfSDavid du Colombier case OIND:
8437dd7cddfSDavid du Colombier if(nn == Z) {
8447dd7cddfSDavid du Colombier nullwarn(n->left, Z);
8457dd7cddfSDavid du Colombier break;
8467dd7cddfSDavid du Colombier }
8477dd7cddfSDavid du Colombier
8487dd7cddfSDavid du Colombier default:
8497dd7cddfSDavid du Colombier goto copy;
8507dd7cddfSDavid du Colombier
8517dd7cddfSDavid du Colombier case ODOT:
8527dd7cddfSDavid du Colombier l = n->left;
8537dd7cddfSDavid du Colombier sugen(l, nodrat, l->type->width);
8547dd7cddfSDavid du Colombier if(nn != Z) {
8557dd7cddfSDavid du Colombier warn(n, "non-interruptable temporary");
8567dd7cddfSDavid du Colombier nod1 = *nodrat;
8577dd7cddfSDavid du Colombier r = n->right;
8587dd7cddfSDavid du Colombier if(!r || r->op != OCONST) {
8597dd7cddfSDavid du Colombier diag(n, "DOT and no offset");
8607dd7cddfSDavid du Colombier break;
8617dd7cddfSDavid du Colombier }
8627dd7cddfSDavid du Colombier nod1.xoffset += (long)r->vconst;
8637dd7cddfSDavid du Colombier nod1.type = n->type;
8647dd7cddfSDavid du Colombier sugen(&nod1, nn, w);
8657dd7cddfSDavid du Colombier }
8667dd7cddfSDavid du Colombier break;
8677dd7cddfSDavid du Colombier
8687dd7cddfSDavid du Colombier case OSTRUCT:
8697dd7cddfSDavid du Colombier /*
8707dd7cddfSDavid du Colombier * rewrite so lhs has no side effects
8717dd7cddfSDavid du Colombier */
8727dd7cddfSDavid du Colombier if(nn != Z && side(nn)) {
8737dd7cddfSDavid du Colombier nod1 = *n;
8747dd7cddfSDavid du Colombier nod1.type = typ(TIND, n->type);
8757dd7cddfSDavid du Colombier regalloc(&nod2, &nod1, Z);
8767dd7cddfSDavid du Colombier lcgen(nn, &nod2);
8777dd7cddfSDavid du Colombier regsalloc(&nod0, &nod1);
8787dd7cddfSDavid du Colombier gopcode(OAS, &nod2, Z, &nod0);
8797dd7cddfSDavid du Colombier regfree(&nod2);
8807dd7cddfSDavid du Colombier
8817dd7cddfSDavid du Colombier nod1 = *n;
8827dd7cddfSDavid du Colombier nod1.op = OIND;
8837dd7cddfSDavid du Colombier nod1.left = &nod0;
8847dd7cddfSDavid du Colombier nod1.right = Z;
8857dd7cddfSDavid du Colombier nod1.complex = 1;
8867dd7cddfSDavid du Colombier
8877dd7cddfSDavid du Colombier sugen(n, &nod1, w);
8887dd7cddfSDavid du Colombier return;
8897dd7cddfSDavid du Colombier }
8907dd7cddfSDavid du Colombier
8917dd7cddfSDavid du Colombier r = n->left;
8927dd7cddfSDavid du Colombier for(t = n->type->link; t != T; t = t->down) {
8937dd7cddfSDavid du Colombier l = r;
8947dd7cddfSDavid du Colombier if(r->op == OLIST) {
8957dd7cddfSDavid du Colombier l = r->left;
8967dd7cddfSDavid du Colombier r = r->right;
8977dd7cddfSDavid du Colombier }
8987dd7cddfSDavid du Colombier if(nn == Z) {
8997dd7cddfSDavid du Colombier cgen(l, nn);
9007dd7cddfSDavid du Colombier continue;
9017dd7cddfSDavid du Colombier }
9027dd7cddfSDavid du Colombier /*
9037dd7cddfSDavid du Colombier * hand craft *(&nn + o) = l
9047dd7cddfSDavid du Colombier */
9057dd7cddfSDavid du Colombier nod0 = znode;
9067dd7cddfSDavid du Colombier nod0.op = OAS;
9077dd7cddfSDavid du Colombier nod0.type = t;
9087dd7cddfSDavid du Colombier nod0.left = &nod1;
9097dd7cddfSDavid du Colombier nod0.right = l;
9107dd7cddfSDavid du Colombier
9117dd7cddfSDavid du Colombier nod1 = znode;
9127dd7cddfSDavid du Colombier nod1.op = OIND;
9137dd7cddfSDavid du Colombier nod1.type = t;
9147dd7cddfSDavid du Colombier nod1.left = &nod2;
9157dd7cddfSDavid du Colombier
9167dd7cddfSDavid du Colombier nod2 = znode;
9177dd7cddfSDavid du Colombier nod2.op = OADD;
9187dd7cddfSDavid du Colombier nod2.type = typ(TIND, t);
9197dd7cddfSDavid du Colombier nod2.left = &nod3;
9207dd7cddfSDavid du Colombier nod2.right = &nod4;
9217dd7cddfSDavid du Colombier
9227dd7cddfSDavid du Colombier nod3 = znode;
9237dd7cddfSDavid du Colombier nod3.op = OADDR;
9247dd7cddfSDavid du Colombier nod3.type = nod2.type;
9257dd7cddfSDavid du Colombier nod3.left = nn;
9267dd7cddfSDavid du Colombier
9277dd7cddfSDavid du Colombier nod4 = znode;
9287dd7cddfSDavid du Colombier nod4.op = OCONST;
9297dd7cddfSDavid du Colombier nod4.type = nod2.type;
9307dd7cddfSDavid du Colombier nod4.vconst = t->offset;
9317dd7cddfSDavid du Colombier
9327dd7cddfSDavid du Colombier ccom(&nod0);
9337dd7cddfSDavid du Colombier acom(&nod0);
9347dd7cddfSDavid du Colombier xcom(&nod0);
9357dd7cddfSDavid du Colombier nod0.addable = 0;
9367dd7cddfSDavid du Colombier
9377dd7cddfSDavid du Colombier /* prtree(&nod0, "hand craft"); /* */
9387dd7cddfSDavid du Colombier cgen(&nod0, Z);
9397dd7cddfSDavid du Colombier }
9407dd7cddfSDavid du Colombier break;
9417dd7cddfSDavid du Colombier
9427dd7cddfSDavid du Colombier case OAS:
9437dd7cddfSDavid du Colombier if(nn == Z) {
9447dd7cddfSDavid du Colombier if(n->addable < INDEXED)
9457dd7cddfSDavid du Colombier sugen(n->right, n->left, w);
9467dd7cddfSDavid du Colombier break;
9477dd7cddfSDavid du Colombier }
9487dd7cddfSDavid du Colombier /* BOTCH -- functions can clobber rathole */
9497dd7cddfSDavid du Colombier sugen(n->right, nodrat, w);
9507dd7cddfSDavid du Colombier warn(n, "non-interruptable temporary");
9517dd7cddfSDavid du Colombier sugen(nodrat, n->left, w);
9527dd7cddfSDavid du Colombier sugen(nodrat, nn, w);
9537dd7cddfSDavid du Colombier break;
9547dd7cddfSDavid du Colombier
9557dd7cddfSDavid du Colombier case OFUNC:
956*6891d857SDavid du Colombier /* this transformation should probably be done earlier */
9577dd7cddfSDavid du Colombier if(nn == Z) {
9587dd7cddfSDavid du Colombier sugen(n, nodrat, w);
9597dd7cddfSDavid du Colombier break;
9607dd7cddfSDavid du Colombier }
9617dd7cddfSDavid du Colombier if(nn->op != OIND) {
9627dd7cddfSDavid du Colombier nn = new1(OADDR, nn, Z);
9637dd7cddfSDavid du Colombier nn->type = types[TIND];
9647dd7cddfSDavid du Colombier nn->addable = 0;
9657dd7cddfSDavid du Colombier } else
9667dd7cddfSDavid du Colombier nn = nn->left;
9677dd7cddfSDavid du Colombier n = new(OFUNC, n->left, new(OLIST, nn, n->right));
968*6891d857SDavid du Colombier n->complex = FNX;
9697dd7cddfSDavid du Colombier n->type = types[TVOID];
9707dd7cddfSDavid du Colombier n->left->type = types[TVOID];
9717dd7cddfSDavid du Colombier cgen(n, Z);
9727dd7cddfSDavid du Colombier break;
9737dd7cddfSDavid du Colombier
9747dd7cddfSDavid du Colombier case OCOND:
9757dd7cddfSDavid du Colombier bcgen(n->left, 1);
9767dd7cddfSDavid du Colombier p1 = p;
9777dd7cddfSDavid du Colombier sugen(n->right->left, nn, w);
9787dd7cddfSDavid du Colombier gbranch(OGOTO);
9797dd7cddfSDavid du Colombier patch(p1, pc);
9807dd7cddfSDavid du Colombier p1 = p;
9817dd7cddfSDavid du Colombier sugen(n->right->right, nn, w);
9827dd7cddfSDavid du Colombier patch(p1, pc);
9837dd7cddfSDavid du Colombier break;
9847dd7cddfSDavid du Colombier
9857dd7cddfSDavid du Colombier case OCOMMA:
9867dd7cddfSDavid du Colombier cgen(n->left, Z);
9877dd7cddfSDavid du Colombier sugen(n->right, nn, w);
9887dd7cddfSDavid du Colombier break;
9897dd7cddfSDavid du Colombier }
9907dd7cddfSDavid du Colombier return;
9917dd7cddfSDavid du Colombier
9927dd7cddfSDavid du Colombier copy:
9937dd7cddfSDavid du Colombier if(nn == Z)
9947dd7cddfSDavid du Colombier return;
9957dd7cddfSDavid du Colombier if(n->complex >= FNX && nn->complex >= FNX) {
9967dd7cddfSDavid du Colombier t = nn->type;
9977dd7cddfSDavid du Colombier nn->type = types[TLONG];
9987dd7cddfSDavid du Colombier regialloc(&nod1, nn, Z);
9997dd7cddfSDavid du Colombier lcgen(nn, &nod1);
10007dd7cddfSDavid du Colombier regsalloc(&nod2, nn);
10017dd7cddfSDavid du Colombier nn->type = t;
10027dd7cddfSDavid du Colombier
1003*6891d857SDavid du Colombier gmove(&nod1, &nod2);
10047dd7cddfSDavid du Colombier regfree(&nod1);
10057dd7cddfSDavid du Colombier
10067dd7cddfSDavid du Colombier nod2.type = typ(TIND, t);
10077dd7cddfSDavid du Colombier
10087dd7cddfSDavid du Colombier nod1 = nod2;
10097dd7cddfSDavid du Colombier nod1.op = OIND;
10107dd7cddfSDavid du Colombier nod1.left = &nod2;
10117dd7cddfSDavid du Colombier nod1.right = Z;
10127dd7cddfSDavid du Colombier nod1.complex = 1;
10137dd7cddfSDavid du Colombier nod1.type = t;
10147dd7cddfSDavid du Colombier
10157dd7cddfSDavid du Colombier sugen(n, &nod1, w);
10167dd7cddfSDavid du Colombier return;
10177dd7cddfSDavid du Colombier }
10187dd7cddfSDavid du Colombier
10197dd7cddfSDavid du Colombier if(n->complex > nn->complex) {
10207dd7cddfSDavid du Colombier t = n->type;
10217dd7cddfSDavid du Colombier n->type = types[TLONG];
10227dd7cddfSDavid du Colombier reglcgen(&nod1, n, Z);
10237dd7cddfSDavid du Colombier n->type = t;
10247dd7cddfSDavid du Colombier
10257dd7cddfSDavid du Colombier t = nn->type;
10267dd7cddfSDavid du Colombier nn->type = types[TLONG];
10277dd7cddfSDavid du Colombier reglcgen(&nod2, nn, Z);
10287dd7cddfSDavid du Colombier nn->type = t;
10297dd7cddfSDavid du Colombier } else {
10307dd7cddfSDavid du Colombier t = nn->type;
10317dd7cddfSDavid du Colombier nn->type = types[TLONG];
10327dd7cddfSDavid du Colombier reglcgen(&nod2, nn, Z);
10337dd7cddfSDavid du Colombier nn->type = t;
10347dd7cddfSDavid du Colombier
10357dd7cddfSDavid du Colombier t = n->type;
10367dd7cddfSDavid du Colombier n->type = types[TLONG];
10377dd7cddfSDavid du Colombier reglcgen(&nod1, n, Z);
10387dd7cddfSDavid du Colombier n->type = t;
10397dd7cddfSDavid du Colombier }
10407dd7cddfSDavid du Colombier
10417dd7cddfSDavid du Colombier w /= SZ_LONG;
10427dd7cddfSDavid du Colombier if(w <= 5) {
10437dd7cddfSDavid du Colombier layout(&nod1, &nod2, w, 0, Z);
10447dd7cddfSDavid du Colombier goto out;
10457dd7cddfSDavid du Colombier }
10467dd7cddfSDavid du Colombier
10477dd7cddfSDavid du Colombier /*
10487dd7cddfSDavid du Colombier * minimize space for unrolling loop
10497dd7cddfSDavid du Colombier * 3,4,5 times. (6 or more is never minimum)
10507dd7cddfSDavid du Colombier * if small structure, try 2 also.
10517dd7cddfSDavid du Colombier */
10527dd7cddfSDavid du Colombier c = 0; /* set */
10537dd7cddfSDavid du Colombier m = 100;
10547dd7cddfSDavid du Colombier i = 3;
10557dd7cddfSDavid du Colombier if(w <= 15)
10567dd7cddfSDavid du Colombier i = 2;
10577dd7cddfSDavid du Colombier for(; i<=5; i++)
10587dd7cddfSDavid du Colombier if(i + w%i <= m) {
10597dd7cddfSDavid du Colombier c = i;
10607dd7cddfSDavid du Colombier m = c + w%c;
10617dd7cddfSDavid du Colombier }
10627dd7cddfSDavid du Colombier
10637dd7cddfSDavid du Colombier regalloc(&nod3, ®node, Z);
10647dd7cddfSDavid du Colombier layout(&nod1, &nod2, w%c, w/c, &nod3);
10657dd7cddfSDavid du Colombier
10667dd7cddfSDavid du Colombier pc1 = pc;
10677dd7cddfSDavid du Colombier layout(&nod1, &nod2, c, 0, Z);
10687dd7cddfSDavid du Colombier
10697dd7cddfSDavid du Colombier gopcode(OSUB, nodconst(1L), Z, &nod3);
10707dd7cddfSDavid du Colombier nod1.op = OREGISTER;
10717dd7cddfSDavid du Colombier gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
10727dd7cddfSDavid du Colombier nod2.op = OREGISTER;
10737dd7cddfSDavid du Colombier gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
10747dd7cddfSDavid du Colombier
10757dd7cddfSDavid du Colombier gopcode(OGT, &nod3, Z, nodconst(0));
10767dd7cddfSDavid du Colombier patch(p, pc1);
10777dd7cddfSDavid du Colombier
10787dd7cddfSDavid du Colombier regfree(&nod3);
10797dd7cddfSDavid du Colombier out:
10807dd7cddfSDavid du Colombier regfree(&nod1);
10817dd7cddfSDavid du Colombier regfree(&nod2);
10827dd7cddfSDavid du Colombier }
10837dd7cddfSDavid du Colombier
10847dd7cddfSDavid du Colombier void
layout(Node * f,Node * t,int c,int cv,Node * cn)10857dd7cddfSDavid du Colombier layout(Node *f, Node *t, int c, int cv, Node *cn)
10867dd7cddfSDavid du Colombier {
10877dd7cddfSDavid du Colombier Node t1, t2;
10887dd7cddfSDavid du Colombier
10897dd7cddfSDavid du Colombier while(c > 3) {
10907dd7cddfSDavid du Colombier layout(f, t, 2, 0, Z);
10917dd7cddfSDavid du Colombier c -= 2;
10927dd7cddfSDavid du Colombier }
10937dd7cddfSDavid du Colombier
10947dd7cddfSDavid du Colombier regalloc(&t1, ®node, Z);
10957dd7cddfSDavid du Colombier regalloc(&t2, ®node, Z);
10967dd7cddfSDavid du Colombier if(c > 0) {
10977dd7cddfSDavid du Colombier gopcode(OAS, f, Z, &t1);
10987dd7cddfSDavid du Colombier f->xoffset += SZ_LONG;
10997dd7cddfSDavid du Colombier }
11007dd7cddfSDavid du Colombier if(cn != Z)
11017dd7cddfSDavid du Colombier gopcode(OAS, nodconst(cv), Z, cn);
11027dd7cddfSDavid du Colombier if(c > 1) {
11037dd7cddfSDavid du Colombier gopcode(OAS, f, Z, &t2);
11047dd7cddfSDavid du Colombier f->xoffset += SZ_LONG;
11057dd7cddfSDavid du Colombier }
11067dd7cddfSDavid du Colombier if(c > 0) {
11077dd7cddfSDavid du Colombier gopcode(OAS, &t1, Z, t);
11087dd7cddfSDavid du Colombier t->xoffset += SZ_LONG;
11097dd7cddfSDavid du Colombier }
11107dd7cddfSDavid du Colombier if(c > 2) {
11117dd7cddfSDavid du Colombier gopcode(OAS, f, Z, &t1);
11127dd7cddfSDavid du Colombier f->xoffset += SZ_LONG;
11137dd7cddfSDavid du Colombier }
11147dd7cddfSDavid du Colombier if(c > 1) {
11157dd7cddfSDavid du Colombier gopcode(OAS, &t2, Z, t);
11167dd7cddfSDavid du Colombier t->xoffset += SZ_LONG;
11177dd7cddfSDavid du Colombier }
11187dd7cddfSDavid du Colombier if(c > 2) {
11197dd7cddfSDavid du Colombier gopcode(OAS, &t1, Z, t);
11207dd7cddfSDavid du Colombier t->xoffset += SZ_LONG;
11217dd7cddfSDavid du Colombier }
11227dd7cddfSDavid du Colombier regfree(&t1);
11237dd7cddfSDavid du Colombier regfree(&t2);
11247dd7cddfSDavid du Colombier }
1125*6891d857SDavid du Colombier
1126*6891d857SDavid du Colombier /*
1127*6891d857SDavid du Colombier * is the vlong's value directly addressible?
1128*6891d857SDavid du Colombier */
1129*6891d857SDavid du Colombier int
isvdirect(Node * n)1130*6891d857SDavid du Colombier isvdirect(Node *n)
1131*6891d857SDavid du Colombier {
1132*6891d857SDavid du Colombier return n->op == ONAME || n->op == OCONST || n->op == OINDREG;
1133*6891d857SDavid du Colombier }
1134*6891d857SDavid du Colombier
1135*6891d857SDavid du Colombier /*
1136*6891d857SDavid du Colombier * can the constant be used with given vlong op?
1137*6891d857SDavid du Colombier */
1138*6891d857SDavid du Colombier static int
isvconstable(int o,vlong v)1139*6891d857SDavid du Colombier isvconstable(int o, vlong v)
1140*6891d857SDavid du Colombier {
1141*6891d857SDavid du Colombier switch(o) {
1142*6891d857SDavid du Colombier case OADD:
1143*6891d857SDavid du Colombier case OASADD:
1144*6891d857SDavid du Colombier /* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */
1145*6891d857SDavid du Colombier return v == 0 || v == -1;
1146*6891d857SDavid du Colombier case OAND:
1147*6891d857SDavid du Colombier case OOR:
1148*6891d857SDavid du Colombier case OXOR:
1149*6891d857SDavid du Colombier case OLSHR:
1150*6891d857SDavid du Colombier case OASHL:
1151*6891d857SDavid du Colombier case OASHR:
1152*6891d857SDavid du Colombier case OASLSHR:
1153*6891d857SDavid du Colombier case OASASHL:
1154*6891d857SDavid du Colombier case OASASHR:
1155*6891d857SDavid du Colombier return 1;
1156*6891d857SDavid du Colombier }
1157*6891d857SDavid du Colombier return 0;
1158*6891d857SDavid du Colombier }
1159*6891d857SDavid du Colombier
1160*6891d857SDavid du Colombier /*
1161*6891d857SDavid du Colombier * most 64-bit operations: cgen into a register pair, then operate.
1162*6891d857SDavid du Colombier * 64-bit comparisons are handled a little differently because the two underlying
1163*6891d857SDavid du Colombier * comparisons can be compiled separately, since the calculations don't interact.
1164*6891d857SDavid du Colombier */
1165*6891d857SDavid du Colombier
1166*6891d857SDavid du Colombier static void
vcgen(Node * n,Node * o,int * f)1167*6891d857SDavid du Colombier vcgen(Node *n, Node *o, int *f)
1168*6891d857SDavid du Colombier {
1169*6891d857SDavid du Colombier *f = 0;
1170*6891d857SDavid du Colombier if(!isvdirect(n)) {
1171*6891d857SDavid du Colombier if(n->complex >= FNX) {
1172*6891d857SDavid du Colombier regsalloc(o, n);
1173*6891d857SDavid du Colombier cgen(n, o);
1174*6891d857SDavid du Colombier return;
1175*6891d857SDavid du Colombier }
1176*6891d857SDavid du Colombier *f = 1;
1177*6891d857SDavid du Colombier if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) {
1178*6891d857SDavid du Colombier regalloc(o, n, Z);
1179*6891d857SDavid du Colombier cgen(n, o);
1180*6891d857SDavid du Colombier } else
1181*6891d857SDavid du Colombier reglcgen(o, n, Z);
1182*6891d857SDavid du Colombier } else
1183*6891d857SDavid du Colombier *o = *n;
1184*6891d857SDavid du Colombier }
1185*6891d857SDavid du Colombier
1186*6891d857SDavid du Colombier static int
isuns(int op)1187*6891d857SDavid du Colombier isuns(int op)
1188*6891d857SDavid du Colombier {
1189*6891d857SDavid du Colombier switch(op){
1190*6891d857SDavid du Colombier case OLO:
1191*6891d857SDavid du Colombier case OLS:
1192*6891d857SDavid du Colombier case OHI:
1193*6891d857SDavid du Colombier case OHS:
1194*6891d857SDavid du Colombier return 1;
1195*6891d857SDavid du Colombier default:
1196*6891d857SDavid du Colombier return 0;
1197*6891d857SDavid du Colombier }
1198*6891d857SDavid du Colombier }
1199*6891d857SDavid du Colombier
1200*6891d857SDavid du Colombier static void
gcmpv(Node * l,Node * r,void (* mov)(Node *,Node *,int),int op)1201*6891d857SDavid du Colombier gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op)
1202*6891d857SDavid du Colombier {
1203*6891d857SDavid du Colombier Node vl, vr;
1204*6891d857SDavid du Colombier
1205*6891d857SDavid du Colombier regalloc(&vl, ®node, Z);
1206*6891d857SDavid du Colombier mov(l, &vl, 0);
1207*6891d857SDavid du Colombier regalloc(&vr, ®node, Z);
1208*6891d857SDavid du Colombier mov(r, &vr, 1+isuns(op));
1209*6891d857SDavid du Colombier gopcode(op, &vl, Z, &vr);
1210*6891d857SDavid du Colombier if(vl.op == OREGISTER)
1211*6891d857SDavid du Colombier regfree(&vl);
1212*6891d857SDavid du Colombier if(vr.op == OREGISTER)
1213*6891d857SDavid du Colombier regfree(&vr);
1214*6891d857SDavid du Colombier }
1215*6891d857SDavid du Colombier
1216*6891d857SDavid du Colombier static void
brcondv(Node * l,Node * r,int chi,int clo)1217*6891d857SDavid du Colombier brcondv(Node *l, Node *r, int chi, int clo)
1218*6891d857SDavid du Colombier {
1219*6891d857SDavid du Colombier Prog *p1, *p2, *p3, *p4;
1220*6891d857SDavid du Colombier
1221*6891d857SDavid du Colombier gcmpv(l, r, gloadhi, chi);
1222*6891d857SDavid du Colombier p1 = p;
1223*6891d857SDavid du Colombier gins(ABNE, Z, Z);
1224*6891d857SDavid du Colombier p2 = p;
1225*6891d857SDavid du Colombier gcmpv(l, r, gloadlo, clo);
1226*6891d857SDavid du Colombier p3 = p;
1227*6891d857SDavid du Colombier gbranch(OGOTO);
1228*6891d857SDavid du Colombier p4 = p;
1229*6891d857SDavid du Colombier patch(p1, pc);
1230*6891d857SDavid du Colombier patch(p3, pc);
1231*6891d857SDavid du Colombier gbranch(OGOTO);
1232*6891d857SDavid du Colombier patch(p2, pc);
1233*6891d857SDavid du Colombier patch(p4, pc);
1234*6891d857SDavid du Colombier }
1235*6891d857SDavid du Colombier
1236*6891d857SDavid du Colombier static void
testv(Node * n,int true)1237*6891d857SDavid du Colombier testv(Node *n, int true)
1238*6891d857SDavid du Colombier {
1239*6891d857SDavid du Colombier Node nod;
1240*6891d857SDavid du Colombier
1241*6891d857SDavid du Colombier nod = znode;
1242*6891d857SDavid du Colombier nod.op = ONE;
1243*6891d857SDavid du Colombier nod.left = n;
1244*6891d857SDavid du Colombier nod.right = new1(0, Z, Z);
1245*6891d857SDavid du Colombier *nod.right = *nodconst(0);
1246*6891d857SDavid du Colombier nod.right->type = n->type;
1247*6891d857SDavid du Colombier nod.type = types[TLONG];
1248*6891d857SDavid du Colombier cmpv(&nod, true, Z);
1249*6891d857SDavid du Colombier }
1250*6891d857SDavid du Colombier
1251*6891d857SDavid du Colombier /*
1252*6891d857SDavid du Colombier * comparison for vlong does high and low order parts separately,
1253*6891d857SDavid du Colombier * which saves loading the latter if the high order comparison suffices
1254*6891d857SDavid du Colombier */
1255*6891d857SDavid du Colombier static void
cmpv(Node * n,int true,Node * nn)1256*6891d857SDavid du Colombier cmpv(Node *n, int true, Node *nn)
1257*6891d857SDavid du Colombier {
1258*6891d857SDavid du Colombier Node *l, *r, nod, nod1;
1259*6891d857SDavid du Colombier int o, f1, f2;
1260*6891d857SDavid du Colombier Prog *p1, *p2;
1261*6891d857SDavid du Colombier long curs;
1262*6891d857SDavid du Colombier
1263*6891d857SDavid du Colombier if(debug['g']) {
1264*6891d857SDavid du Colombier if(nn != nil)
1265*6891d857SDavid du Colombier prtree(nn, "cmpv lhs");
1266*6891d857SDavid du Colombier prtree(n, "cmpv");
1267*6891d857SDavid du Colombier }
1268*6891d857SDavid du Colombier curs = cursafe;
1269*6891d857SDavid du Colombier l = n->left;
1270*6891d857SDavid du Colombier r = n->right;
1271*6891d857SDavid du Colombier if(l->complex >= FNX && r->complex >= FNX) {
1272*6891d857SDavid du Colombier regsalloc(&nod1, r);
1273*6891d857SDavid du Colombier cgen(r, &nod1);
1274*6891d857SDavid du Colombier nod = *n;
1275*6891d857SDavid du Colombier nod.right = &nod1;
1276*6891d857SDavid du Colombier cmpv(&nod, true, nn);
1277*6891d857SDavid du Colombier cursafe = curs;
1278*6891d857SDavid du Colombier return;
1279*6891d857SDavid du Colombier }
1280*6891d857SDavid du Colombier if(l->complex >= r->complex) {
1281*6891d857SDavid du Colombier vcgen(l, &nod1, &f1);
1282*6891d857SDavid du Colombier vcgen(r, &nod, &f2);
1283*6891d857SDavid du Colombier } else {
1284*6891d857SDavid du Colombier vcgen(r, &nod, &f2);
1285*6891d857SDavid du Colombier vcgen(l, &nod1, &f1);
1286*6891d857SDavid du Colombier }
1287*6891d857SDavid du Colombier nod.type = types[TLONG];
1288*6891d857SDavid du Colombier nod1.type = types[TLONG];
1289*6891d857SDavid du Colombier o = n->op;
1290*6891d857SDavid du Colombier if(true)
1291*6891d857SDavid du Colombier o = comrel[relindex(o)];
1292*6891d857SDavid du Colombier switch(o){
1293*6891d857SDavid du Colombier case OEQ:
1294*6891d857SDavid du Colombier gcmpv(&nod1, &nod, gloadhi, ONE);
1295*6891d857SDavid du Colombier p1 = p;
1296*6891d857SDavid du Colombier gcmpv(&nod1, &nod, gloadlo, ONE);
1297*6891d857SDavid du Colombier p2 = p;
1298*6891d857SDavid du Colombier gbranch(OGOTO);
1299*6891d857SDavid du Colombier patch(p1, pc);
1300*6891d857SDavid du Colombier patch(p2, pc);
1301*6891d857SDavid du Colombier break;
1302*6891d857SDavid du Colombier case ONE:
1303*6891d857SDavid du Colombier gcmpv(&nod1, &nod, gloadhi, ONE);
1304*6891d857SDavid du Colombier p1 = p;
1305*6891d857SDavid du Colombier gcmpv(&nod1, &nod, gloadlo, OEQ);
1306*6891d857SDavid du Colombier p2 = p;
1307*6891d857SDavid du Colombier patch(p1, pc);
1308*6891d857SDavid du Colombier gbranch(OGOTO);
1309*6891d857SDavid du Colombier patch(p2, pc);
1310*6891d857SDavid du Colombier break;
1311*6891d857SDavid du Colombier case OLE:
1312*6891d857SDavid du Colombier brcondv(&nod1, &nod, OLT, OLS);
1313*6891d857SDavid du Colombier break;
1314*6891d857SDavid du Colombier case OGT:
1315*6891d857SDavid du Colombier brcondv(&nod1, &nod, OGT, OHI);
1316*6891d857SDavid du Colombier break;
1317*6891d857SDavid du Colombier case OLS:
1318*6891d857SDavid du Colombier brcondv(&nod1, &nod, OLO, OLS);
1319*6891d857SDavid du Colombier break;
1320*6891d857SDavid du Colombier case OHI:
1321*6891d857SDavid du Colombier brcondv(&nod1, &nod, OHI, OHI);
1322*6891d857SDavid du Colombier break;
1323*6891d857SDavid du Colombier case OLT:
1324*6891d857SDavid du Colombier brcondv(&nod1, &nod, OLT, OLO);
1325*6891d857SDavid du Colombier break;
1326*6891d857SDavid du Colombier case OGE:
1327*6891d857SDavid du Colombier brcondv(&nod1, &nod, OGT, OHS);
1328*6891d857SDavid du Colombier break;
1329*6891d857SDavid du Colombier case OLO:
1330*6891d857SDavid du Colombier brcondv(&nod1, &nod, OLO, OLO);
1331*6891d857SDavid du Colombier break;
1332*6891d857SDavid du Colombier case OHS:
1333*6891d857SDavid du Colombier brcondv(&nod1, &nod, OHI, OHS);
1334*6891d857SDavid du Colombier break;
1335*6891d857SDavid du Colombier default:
1336*6891d857SDavid du Colombier diag(n, "bad cmpv");
1337*6891d857SDavid du Colombier return;
1338*6891d857SDavid du Colombier }
1339*6891d857SDavid du Colombier if(f1)
1340*6891d857SDavid du Colombier regfree(&nod1);
1341*6891d857SDavid du Colombier if(f2)
1342*6891d857SDavid du Colombier regfree(&nod);
1343*6891d857SDavid du Colombier cursafe = curs;
1344*6891d857SDavid du Colombier }
1345*6891d857SDavid du Colombier
1346*6891d857SDavid du Colombier static void
cgen64(Node * n,Node * nn)1347*6891d857SDavid du Colombier cgen64(Node *n, Node *nn)
1348*6891d857SDavid du Colombier {
1349*6891d857SDavid du Colombier Node *l, *r, *d;
1350*6891d857SDavid du Colombier Node nod, nod1;
1351*6891d857SDavid du Colombier long curs;
1352*6891d857SDavid du Colombier Type *t;
1353*6891d857SDavid du Colombier int o, m;
1354*6891d857SDavid du Colombier
1355*6891d857SDavid du Colombier curs = cursafe;
1356*6891d857SDavid du Colombier l = n->left;
1357*6891d857SDavid du Colombier r = n->right;
1358*6891d857SDavid du Colombier o = n->op;
1359*6891d857SDavid du Colombier switch(o) {
1360*6891d857SDavid du Colombier
1361*6891d857SDavid du Colombier case OCONST:
1362*6891d857SDavid du Colombier if(nn == Z) {
1363*6891d857SDavid du Colombier nullwarn(n->left, Z);
1364*6891d857SDavid du Colombier break;
1365*6891d857SDavid du Colombier }
1366*6891d857SDavid du Colombier if(nn->op != OREGPAIR) {
1367*6891d857SDavid du Colombier //prtree(n, "cgen64 const");
1368*6891d857SDavid du Colombier t = nn->type;
1369*6891d857SDavid du Colombier nn->type = types[TLONG];
1370*6891d857SDavid du Colombier reglcgen(&nod1, nn, Z);
1371*6891d857SDavid du Colombier nn->type = t;
1372*6891d857SDavid du Colombier
1373*6891d857SDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
1374*6891d857SDavid du Colombier gmove(nod32const(n->vconst>>32), &nod1);
1375*6891d857SDavid du Colombier else
1376*6891d857SDavid du Colombier gmove(nod32const(n->vconst), &nod1);
1377*6891d857SDavid du Colombier nod1.xoffset += SZ_LONG;
1378*6891d857SDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
1379*6891d857SDavid du Colombier gmove(nod32const(n->vconst), &nod1);
1380*6891d857SDavid du Colombier else
1381*6891d857SDavid du Colombier gmove(nod32const(n->vconst>>32), &nod1);
1382*6891d857SDavid du Colombier
1383*6891d857SDavid du Colombier regfree(&nod1);
1384*6891d857SDavid du Colombier } else
1385*6891d857SDavid du Colombier gmove(n, nn);
1386*6891d857SDavid du Colombier break;
1387*6891d857SDavid du Colombier
1388*6891d857SDavid du Colombier case OCAST:
1389*6891d857SDavid du Colombier /*
1390*6891d857SDavid du Colombier * convert from types l->n->nn
1391*6891d857SDavid du Colombier */
1392*6891d857SDavid du Colombier if(typev[l->type->etype]){
1393*6891d857SDavid du Colombier /* vlong to non-vlong */
1394*6891d857SDavid du Colombier if(!isvdirect(l)) {
1395*6891d857SDavid du Colombier if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) {
1396*6891d857SDavid du Colombier regalloc(&nod, l, l);
1397*6891d857SDavid du Colombier cgen(l, &nod);
1398*6891d857SDavid du Colombier regalloc(&nod1, n, nn);
1399*6891d857SDavid du Colombier gmove(nod.right, &nod1);
1400*6891d857SDavid du Colombier } else {
1401*6891d857SDavid du Colombier reglcgen(&nod, l, Z);
1402*6891d857SDavid du Colombier regalloc(&nod1, n, nn);
1403*6891d857SDavid du Colombier gloadlo(&nod, &nod1, 0); /* TO DO: not correct for typefd */
1404*6891d857SDavid du Colombier }
1405*6891d857SDavid du Colombier regfree(&nod);
1406*6891d857SDavid du Colombier } else {
1407*6891d857SDavid du Colombier regalloc(&nod1, n, nn);
1408*6891d857SDavid du Colombier gloadlo(l, &nod1, 0); /* TO DO: not correct for typefd */
1409*6891d857SDavid du Colombier }
1410*6891d857SDavid du Colombier }else{
1411*6891d857SDavid du Colombier /* non-vlong to vlong */
1412*6891d857SDavid du Colombier regalloc(&nod, l, Z);
1413*6891d857SDavid du Colombier cgen(l, &nod);
1414*6891d857SDavid du Colombier regalloc(&nod1, n, nn);
1415*6891d857SDavid du Colombier gmove(&nod, nod1.right);
1416*6891d857SDavid du Colombier if(typeu[l->type->etype])
1417*6891d857SDavid du Colombier gmove(nodconst(0), nod1.left);
1418*6891d857SDavid du Colombier else
1419*6891d857SDavid du Colombier gopcode(OASHR, nodconst(31), nod1.right, nod1.left);
1420*6891d857SDavid du Colombier regfree(&nod);
1421*6891d857SDavid du Colombier }
1422*6891d857SDavid du Colombier gmove(&nod1, nn);
1423*6891d857SDavid du Colombier regfree(&nod1);
1424*6891d857SDavid du Colombier break;
1425*6891d857SDavid du Colombier
1426*6891d857SDavid du Colombier case OFUNC:
1427*6891d857SDavid du Colombier /* this transformation should probably be done earlier */
1428*6891d857SDavid du Colombier if(nn == Z) {
1429*6891d857SDavid du Colombier regsalloc(&nod1, n);
1430*6891d857SDavid du Colombier nn = &nod1;
1431*6891d857SDavid du Colombier }
1432*6891d857SDavid du Colombier m = 0;
1433*6891d857SDavid du Colombier if(nn->op != OIND) {
1434*6891d857SDavid du Colombier if(nn->op == OREGPAIR) {
1435*6891d857SDavid du Colombier m = 1;
1436*6891d857SDavid du Colombier regsalloc(&nod1, nn);
1437*6891d857SDavid du Colombier d = &nod1;
1438*6891d857SDavid du Colombier }else
1439*6891d857SDavid du Colombier d = nn;
1440*6891d857SDavid du Colombier d = new1(OADDR, d, Z);
1441*6891d857SDavid du Colombier d->type = types[TIND];
1442*6891d857SDavid du Colombier d->addable = 0;
1443*6891d857SDavid du Colombier } else
1444*6891d857SDavid du Colombier d = nn->left;
1445*6891d857SDavid du Colombier n = new(OFUNC, l, new(OLIST, d, r));
1446*6891d857SDavid du Colombier n->complex = FNX;
1447*6891d857SDavid du Colombier n->type = types[TVOID];
1448*6891d857SDavid du Colombier n->left->type = types[TVOID];
1449*6891d857SDavid du Colombier cgen(n, Z);
1450*6891d857SDavid du Colombier if(m)
1451*6891d857SDavid du Colombier gmove(&nod1, nn);
1452*6891d857SDavid du Colombier break;
1453*6891d857SDavid du Colombier
1454*6891d857SDavid du Colombier default:
1455*6891d857SDavid du Colombier diag(n, "bad cgen64 %O", o);
1456*6891d857SDavid du Colombier break;
1457*6891d857SDavid du Colombier }
1458*6891d857SDavid du Colombier cursafe = curs;
1459*6891d857SDavid du Colombier }
1460