xref: /plan9/sys/src/cmd/qc/sgen.c (revision 6891d8578618fb7ccda4a131c122d4d0e6580c4b)
17dd7cddfSDavid du Colombier #include "gc.h"
27dd7cddfSDavid du Colombier 
37dd7cddfSDavid du Colombier void
noretval(int n)47dd7cddfSDavid du Colombier noretval(int n)
57dd7cddfSDavid du Colombier {
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier 	if(n & 1) {
87dd7cddfSDavid du Colombier 		gins(ANOP, Z, Z);
97dd7cddfSDavid du Colombier 		p->to.type = D_REG;
107dd7cddfSDavid du Colombier 		p->to.reg = REGRET;
117dd7cddfSDavid du Colombier 	}
127dd7cddfSDavid du Colombier 	if(n & 2) {
137dd7cddfSDavid du Colombier 		gins(ANOP, Z, Z);
147dd7cddfSDavid du Colombier 		p->to.type = D_FREG;
157dd7cddfSDavid du Colombier 		p->to.reg = FREGRET;
167dd7cddfSDavid du Colombier 	}
177dd7cddfSDavid du Colombier }
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier /*
207dd7cddfSDavid du Colombier  *	calculate addressability as follows
217dd7cddfSDavid du Colombier  *		CONST ==> 20		$value
227dd7cddfSDavid du Colombier  *		NAME ==> 10		name
237dd7cddfSDavid du Colombier  *		REGISTER ==> 11		register
247dd7cddfSDavid du Colombier  *		INDREG ==> 12		*[(reg)+offset]
257dd7cddfSDavid du Colombier  *		&10 ==> 2		$name
267dd7cddfSDavid du Colombier  *		ADD(2, 20) ==> 2	$name+offset
277dd7cddfSDavid du Colombier  *		ADD(3, 20) ==> 3	$(reg)+offset
287dd7cddfSDavid du Colombier  *		&12 ==> 3		$(reg)+offset
297dd7cddfSDavid du Colombier  *		*11 ==> 11		??
307dd7cddfSDavid du Colombier  *		*2 ==> 10		name
317dd7cddfSDavid du Colombier  *		*3 ==> 12		*(reg)+offset
327dd7cddfSDavid du Colombier  *	calculate complexity (number of registers)
337dd7cddfSDavid du Colombier  */
347dd7cddfSDavid du Colombier void
xcom(Node * n)357dd7cddfSDavid du Colombier xcom(Node *n)
367dd7cddfSDavid du Colombier {
377dd7cddfSDavid du Colombier 	Node *l, *r;
38*6891d857SDavid du Colombier 	int v, nr;
397dd7cddfSDavid du Colombier 
407dd7cddfSDavid du Colombier 	if(n == Z)
417dd7cddfSDavid du Colombier 		return;
427dd7cddfSDavid du Colombier 	l = n->left;
437dd7cddfSDavid du Colombier 	r = n->right;
447dd7cddfSDavid du Colombier 	n->addable = 0;
457dd7cddfSDavid du Colombier 	n->complex = 0;
467dd7cddfSDavid du Colombier 	switch(n->op) {
477dd7cddfSDavid du Colombier 	case OCONST:
487dd7cddfSDavid du Colombier 		n->addable = 20;
497dd7cddfSDavid du Colombier 		return;
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier 	case OREGISTER:
527dd7cddfSDavid du Colombier 		n->addable = 11;
537dd7cddfSDavid du Colombier 		return;
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	case OINDREG:
567dd7cddfSDavid du Colombier 		n->addable = 12;
577dd7cddfSDavid du Colombier 		return;
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier 	case ONAME:
607dd7cddfSDavid du Colombier 		n->addable = 10;
617dd7cddfSDavid du Colombier 		return;
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier 	case OADDR:
647dd7cddfSDavid du Colombier 		xcom(l);
657dd7cddfSDavid du Colombier 		if(l->addable == 10)
667dd7cddfSDavid du Colombier 			n->addable = 2;
677dd7cddfSDavid du Colombier 		if(l->addable == 12)
687dd7cddfSDavid du Colombier 			n->addable = 3;
697dd7cddfSDavid du Colombier 		break;
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier 	case OIND:
727dd7cddfSDavid du Colombier 		xcom(l);
737dd7cddfSDavid du Colombier 		if(l->addable == 11)
747dd7cddfSDavid du Colombier 			n->addable = 12;
757dd7cddfSDavid du Colombier 		if(l->addable == 3)
767dd7cddfSDavid du Colombier 			n->addable = 12;
777dd7cddfSDavid du Colombier 		if(l->addable == 2)
787dd7cddfSDavid du Colombier 			n->addable = 10;
797dd7cddfSDavid du Colombier 		break;
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 	case OADD:
827dd7cddfSDavid du Colombier 		xcom(l);
837dd7cddfSDavid du Colombier 		xcom(r);
847dd7cddfSDavid du Colombier 		if(l->addable == 20) {
857dd7cddfSDavid du Colombier 			if(r->addable == 2)
867dd7cddfSDavid du Colombier 				n->addable = 2;
877dd7cddfSDavid du Colombier 			if(r->addable == 3)
887dd7cddfSDavid du Colombier 				n->addable = 3;
897dd7cddfSDavid du Colombier 		}
907dd7cddfSDavid du Colombier 		if(r->addable == 20) {
917dd7cddfSDavid du Colombier 			if(l->addable == 2)
927dd7cddfSDavid du Colombier 				n->addable = 2;
937dd7cddfSDavid du Colombier 			if(l->addable == 3)
947dd7cddfSDavid du Colombier 				n->addable = 3;
957dd7cddfSDavid du Colombier 		}
967dd7cddfSDavid du Colombier 		break;
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier 	case OASMUL:
997dd7cddfSDavid du Colombier 	case OASLMUL:
1007dd7cddfSDavid du Colombier 		xcom(l);
1017dd7cddfSDavid du Colombier 		xcom(r);
1027dd7cddfSDavid du Colombier 		v = vlog(r);
1037dd7cddfSDavid du Colombier 		if(v >= 0) {
1047dd7cddfSDavid du Colombier 			n->op = OASASHL;
1057dd7cddfSDavid du Colombier 			r->vconst = v;
1067dd7cddfSDavid du Colombier 			r->type = types[TINT];
1077dd7cddfSDavid du Colombier 		}
1087dd7cddfSDavid du Colombier 		break;
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier 	case OMUL:
1117dd7cddfSDavid du Colombier 	case OLMUL:
1127dd7cddfSDavid du Colombier 		xcom(l);
1137dd7cddfSDavid du Colombier 		xcom(r);
1147dd7cddfSDavid du Colombier 		v = vlog(r);
1157dd7cddfSDavid du Colombier 		if(v >= 0) {
1167dd7cddfSDavid du Colombier 			n->op = OASHL;
1177dd7cddfSDavid du Colombier 			r->vconst = v;
1187dd7cddfSDavid du Colombier 			r->type = types[TINT];
1197dd7cddfSDavid du Colombier 		}
1207dd7cddfSDavid du Colombier 		v = vlog(l);
1217dd7cddfSDavid du Colombier 		if(v >= 0) {
1227dd7cddfSDavid du Colombier 			n->op = OASHL;
1237dd7cddfSDavid du Colombier 			n->left = r;
1247dd7cddfSDavid du Colombier 			n->right = l;
1257dd7cddfSDavid du Colombier 			r = l;
1267dd7cddfSDavid du Colombier 			l = n->left;
1277dd7cddfSDavid du Colombier 			r->vconst = v;
1287dd7cddfSDavid du Colombier 			r->type = types[TINT];
129375daca8SDavid du Colombier 			simplifyshift(n);
1307dd7cddfSDavid du Colombier 		}
1317dd7cddfSDavid du Colombier 		break;
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier 	case OASLDIV:
1347dd7cddfSDavid du Colombier 		xcom(l);
1357dd7cddfSDavid du Colombier 		xcom(r);
1367dd7cddfSDavid du Colombier 		v = vlog(r);
1377dd7cddfSDavid du Colombier 		if(v >= 0) {
1387dd7cddfSDavid du Colombier 			n->op = OASLSHR;
1397dd7cddfSDavid du Colombier 			r->vconst = v;
1407dd7cddfSDavid du Colombier 			r->type = types[TINT];
1417dd7cddfSDavid du Colombier 		}
1427dd7cddfSDavid du Colombier 		break;
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	case OLDIV:
1457dd7cddfSDavid du Colombier 		xcom(l);
1467dd7cddfSDavid du Colombier 		xcom(r);
1477dd7cddfSDavid du Colombier 		v = vlog(r);
1487dd7cddfSDavid du Colombier 		if(v >= 0) {
1497dd7cddfSDavid du Colombier 			n->op = OLSHR;
1507dd7cddfSDavid du Colombier 			r->vconst = v;
1517dd7cddfSDavid du Colombier 			r->type = types[TINT];
152375daca8SDavid du Colombier 			simplifyshift(n);
1537dd7cddfSDavid du Colombier 		}
1547dd7cddfSDavid du Colombier 		break;
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier 	case OASLMOD:
1577dd7cddfSDavid du Colombier 		xcom(l);
1587dd7cddfSDavid du Colombier 		xcom(r);
1597dd7cddfSDavid du Colombier 		v = vlog(r);
1607dd7cddfSDavid du Colombier 		if(v >= 0) {
1617dd7cddfSDavid du Colombier 			n->op = OASAND;
1627dd7cddfSDavid du Colombier 			r->vconst--;
1637dd7cddfSDavid du Colombier 		}
1647dd7cddfSDavid du Colombier 		break;
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier 	case OLMOD:
1677dd7cddfSDavid du Colombier 		xcom(l);
1687dd7cddfSDavid du Colombier 		xcom(r);
1697dd7cddfSDavid du Colombier 		v = vlog(r);
1707dd7cddfSDavid du Colombier 		if(v >= 0) {
1717dd7cddfSDavid du Colombier 			n->op = OAND;
1727dd7cddfSDavid du Colombier 			r->vconst--;
1737dd7cddfSDavid du Colombier 		}
1747dd7cddfSDavid du Colombier 		break;
1757dd7cddfSDavid du Colombier 
176375daca8SDavid du Colombier 	case OLSHR:
177375daca8SDavid du Colombier 	case OASHL:
178375daca8SDavid du Colombier 	case OASHR:
179375daca8SDavid du Colombier 		xcom(l);
180375daca8SDavid du Colombier 		xcom(r);
181375daca8SDavid du Colombier 		simplifyshift(n);
182375daca8SDavid du Colombier 		break;
183375daca8SDavid du Colombier 
1847dd7cddfSDavid du Colombier 	default:
1857dd7cddfSDavid du Colombier 		if(l != Z)
1867dd7cddfSDavid du Colombier 			xcom(l);
1877dd7cddfSDavid du Colombier 		if(r != Z)
1887dd7cddfSDavid du Colombier 			xcom(r);
1897dd7cddfSDavid du Colombier 		break;
1907dd7cddfSDavid du Colombier 	}
1917dd7cddfSDavid du Colombier 	if(n->addable >= 10)
1927dd7cddfSDavid du Colombier 		return;
1937dd7cddfSDavid du Colombier 	if(l != Z)
1947dd7cddfSDavid du Colombier 		n->complex = l->complex;
1957dd7cddfSDavid du Colombier 	if(r != Z) {
196*6891d857SDavid du Colombier 		nr = 1;
197*6891d857SDavid du Colombier 		if(r->type != T && typev[r->type->etype] || n->type != T && typev[n->type->etype]) {
198*6891d857SDavid du Colombier 			nr = 2;
199*6891d857SDavid du Colombier 			if(n->op == OMUL || n->op == OLMUL)
200*6891d857SDavid du Colombier 				nr += 3;
201*6891d857SDavid du Colombier 		}
2027dd7cddfSDavid du Colombier 		if(r->complex == n->complex)
203*6891d857SDavid du Colombier 			n->complex = r->complex+nr;
2047dd7cddfSDavid du Colombier 		else
2057dd7cddfSDavid du Colombier 		if(r->complex > n->complex)
2067dd7cddfSDavid du Colombier 			n->complex = r->complex;
2077dd7cddfSDavid du Colombier 	}
208*6891d857SDavid du Colombier 	if(n->complex == 0){
2097dd7cddfSDavid du Colombier 		n->complex++;
210*6891d857SDavid du Colombier 		if(n->type != T && typev[n->type->etype])
211*6891d857SDavid du Colombier 			n->complex++;
212*6891d857SDavid du Colombier 	}
2137dd7cddfSDavid du Colombier 
2147dd7cddfSDavid du Colombier 	if(com64(n))
2157dd7cddfSDavid du Colombier 		return;
2167dd7cddfSDavid du Colombier 
2177dd7cddfSDavid du Colombier 	switch(n->op) {
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier 	case OFUNC:
2207dd7cddfSDavid du Colombier 		n->complex = FNX;
2217dd7cddfSDavid du Colombier 		break;
2227dd7cddfSDavid du Colombier 
2237dd7cddfSDavid du Colombier 	case OEQ:
2247dd7cddfSDavid du Colombier 	case ONE:
2257dd7cddfSDavid du Colombier 	case OLE:
2267dd7cddfSDavid du Colombier 	case OLT:
2277dd7cddfSDavid du Colombier 	case OGE:
2287dd7cddfSDavid du Colombier 	case OGT:
2297dd7cddfSDavid du Colombier 	case OHI:
2307dd7cddfSDavid du Colombier 	case OHS:
2317dd7cddfSDavid du Colombier 	case OLO:
2327dd7cddfSDavid du Colombier 	case OLS:
2337dd7cddfSDavid du Colombier 		/*
2347dd7cddfSDavid du Colombier 		 * immediate operators, make const on right
2357dd7cddfSDavid du Colombier 		 */
2367dd7cddfSDavid du Colombier 		if(l->op == OCONST) {
2377dd7cddfSDavid du Colombier 			n->left = r;
2387dd7cddfSDavid du Colombier 			n->right = l;
2397dd7cddfSDavid du Colombier 			n->op = invrel[relindex(n->op)];
2407dd7cddfSDavid du Colombier 		}
2417dd7cddfSDavid du Colombier 		break;
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier 	case OADD:
2447dd7cddfSDavid du Colombier 	case OXOR:
2457dd7cddfSDavid du Colombier 	case OAND:
2467dd7cddfSDavid du Colombier 	case OOR:
2477dd7cddfSDavid du Colombier 		/*
2487dd7cddfSDavid du Colombier 		 * immediate operators, make const on right
2497dd7cddfSDavid du Colombier 		 */
2507dd7cddfSDavid du Colombier 		if(l->op == OCONST) {
2517dd7cddfSDavid du Colombier 			n->left = r;
2527dd7cddfSDavid du Colombier 			n->right = l;
2537dd7cddfSDavid du Colombier 		}
2547dd7cddfSDavid du Colombier 		break;
2557dd7cddfSDavid du Colombier 	}
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier 
258