xref: /csrg-svn/old/pcc/c2.tahoe/c21.c (revision 29670)
1 #ifndef lint
2 static char sccsid[] = "@(#)c21.c	1.2 (Berkeley) 07/27/86";
3 #endif
4 
5 /*
6  * C object code improver-- second part
7  */
8 
9 #include "c2.h"
10 #include <stdio.h>
11 #include <ctype.h>
12 
13 int bitsize[] = {0,8,16,32,64,32,64}; /* index by type codes */
14 
15 redun3(p) register struct node *p; {
16 /* check for 3 addr instr which should be 2 addr */
17 	if (OP3==((p->subop>>4)&0xF)) {
18 		if (equstr(regs[RT1],regs[RT3])
19 		  && (p->op==ADD || p->op==MUL || p->op==AND || p->op==OR || p->op==XOR)) {
20 			register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t;
21 		}
22 		if (equstr(regs[RT2],regs[RT3])) {
23 			p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0;
24 			lastrand=regs[RT2]; *regs[RT3]=0; return(1);
25 		}
26 	} return(0);
27 }
28 
29 bmove() {
30 	register struct node *p, *lastp; register char *cp1,*cp2; register int r;
31 	struct node *flops();
32 
33 	refcount();
34 	for (p=lastp= &first; 0!=(p=p->forw); lastp=p);
35 	clearreg(); clearuse();
36 	for (p=lastp; p!= &first; p=p->back) {
37 	if (debug) {
38 		printf("Uses: ");
39 		if (useacc)
40 			printf("acc: %s\n",useacc->code? useacc->code:"");
41 		for (r=NUSE;--r>=0;) if (uses[r])
42 			printf("%d: %s\n",r,uses[r]->code? uses[r]->code:"");
43 		printf("-\n");
44 	}
45 	r=(p->subop>>4)&0xF;
46 	splitrand(p);
47 	if (OP3==r && 0!=redun3(p)) {newcode(p); redunm++;}
48 		/* ops that do nothing */
49 	if(p->op==MOV && equstr(regs[RT1], regs[RT2]))
50 		if(p->forw->op!=CBR) {
51 			delnode(p); redunm++; continue;
52 		} else {
53 			p->op=TST; p->pop=0;
54 			while(*p->code++ != ',');
55 			redunm++;
56 		}
57 	else if((cp1=p->code, *cp1++)=='$' &&
58 	 (*cp1=='0' || *cp1=='1' || *cp1++=='-' && *cp1=='1') && cp1[1]==',') {
59 		switch((p->code[1]<<8)|p->op) {
60 		case (('0'<<8)|ADD):
61 		case (('0'<<8)|SUB):
62 		case (('-'<<8)|AND):
63 		case (('0'<<8)|OR):
64 		case (('0'<<8)|XOR):
65 		case (('1'<<8)|MUL):
66 		case (('1'<<8)|DIV):
67 		case (('0'<<8)|SHAL):
68 		case (('0'<<8)|SHAR):
69 		case (('0'<<8)|SHL):
70 		case (('0'<<8)|SHR):
71 			if(r == OP2) {
72 				if(p->forw->op!=CBR) {
73 					delnode(p); redunm++; continue;
74 				} else {
75 					p->op=TST; p->subop&=0xF; p->pop=0;
76 					while(*p->code++ != ',');
77 					redunm++;
78 				}
79 			} else {	/* OP3 or shift */
80 				p->op=MOV; p->subop&=0xF; p->pop=0;
81 				while(*p->code++ != ',');
82 				p = p->forw; redunm++; continue;
83 			}
84 			break;
85 		case (('0'<<8)|MUL):
86 		case (('0'<<8)|AND):
87 			p->op=CLR; p->subop&=0xF; p->pop=0;
88 			while(*p->code++ != ',');
89 			if(r == OP3)
90 				while(*p->code++ != ',');
91 			redunm++;
92 		}
93 	}
94 	switch (p->op) {
95 	case LABEL: case DLABEL:
96 		for (r=NUSE; --r>=0;)
97 			if (uses[r]) p->ref=(struct node *) (((int)p->ref)|(1<<r));
98 			if (useacc) p->ref=(struct node *) (((int)p->ref)|(1<<NUSE));
99 		break;
100 	case CALLS:
101 	case CALLF:
102 		clearuse(); goto std;
103 	case 0:
104 		clearuse(); break;
105 	case CVT:
106 		{ long n;
107 		if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
108 		if (*cp1++!='$') goto std; splitrand(p);
109 		n = getnum(&regs[RT1][1]);
110 		if(r==BYTE && (n<-128 || n>127)) goto std;
111 		if(r==WORD && (n<-32768 || n>32767)) goto std;
112 		p->op = MOV; p->subop = r; p->pop = 0;
113 		} goto std;
114 
115 	case SUB:
116 		if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
117 		if (*cp1++!='$') goto std; splitrand(p);
118 #ifdef MOVAFASTER
119 		if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
120 			char buf[C2_ASIZE]; cp2=buf; *cp2++='-';
121 			cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
122 			cp1="(fp),"; while (*cp2++= *cp1++); --cp2;
123 			cp1=regs[RT3]; while (*cp2++= *cp1++);
124 			p->code=copy(buf); p->op = MOVA; p->subop = BYTE; p->pop=0;
125 		} else
126 #endif MOVAFASTER
127 		if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
128 		!checkexpr(cp1)) {
129 			p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1;
130 		} goto std;
131 	case ADD:
132 		if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
133 		if (*cp1++!='$') goto std; splitrand(p);
134 		if (isstatic(cp1) && (r=isreg(regs[RT2]))>=0 && r<NUSE && uses[r]==p->forw)
135 		{
136 			/* address comp:
137 			**	addl2	$_foo,r0  \	movab	_foo[r0],bar
138 			**	movl	r0,bar	  /
139 			*/
140 			register struct	node	*pnext = p->forw;
141 			char	buf[C2_ASIZE];
142 
143 			if (pnext->op == MOV && pnext->subop == LONG)
144 			{
145 				cp1 = &regs[RT1][1]; cp2 = &buf[0];
146 				while (*cp2++ = *cp1++) ; cp2--;
147 				splitrand(pnext);
148 				if (r == isreg(regs[RT1]))
149 				{
150 					delnode(p); p = pnext;
151 					p->op = MOVA; p->subop = BYTE;
152 					p->pop = 0;
153 					cp1 = regs[RT1]; *cp2++ = '[';
154 					while (*cp2++ = *cp1++) ; cp2--;
155 					*cp2++ = ']'; *cp2++ = ',';
156 					cp1 = regs[RT2];
157 					while (*cp2++ = *cp1++) ;
158 					p->code = copy(buf);
159 				}
160 			}
161 		}
162 		else
163 #ifdef MOVAFASTER
164 		if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
165 			cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
166 			cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=',';
167 			p->op = MOVA; p->subop = BYTE; p->pop=0;
168 		} else
169 #endif MOVAFASTER
170 		if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
171 		!checkexpr(cp1)) {
172 			p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1;
173 		}
174 		/* fall thru ... */
175 	case CASE:
176 	default: std:
177 		p=bflow(p); break;
178 
179 	case MUL:
180 		/*
181 		** Change multiplication
182 		** by constant powers of 2 to shifts.
183 		*/
184 		splitrand(p);
185 		if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std;
186 		if ((r = ispow2(getnum(&regs[RT1][1]))) <= 0) goto std;
187  		/* mull2 $2,x */
188 		if(r == 1 && p->subop == U(LONG, OP2)) {
189 			strcpy(regs[RT1], regs[RT2]);
190 			p->op = ADD; p->pop = 0; newcode(p);
191 			goto std;
192 		}
193 		if (p->subop == U(LONG,OP2))
194 			strcpy(regs[RT3], regs[RT2]);
195 		sprintf(regs[RT1], "$%d", r);
196 		p->op = SHL; p->subop = LONG;
197 		p->pop = 0; newcode(p);
198 		goto std;
199 
200 	case SHAL:
201 	case SHL:
202 	{
203 		/* bit tests:
204 		**	shll	A,$1,rC    \
205 		**	bitl	B,rC	    >	jbc	A,B,D
206 		**	jeql	D	   /
207 		**
208 		** address comp:
209 		**	shll	$1,bar,r0  \	movl	bar,r0
210 		**	movab	_foo[r0]   /	movaw	_foo[r0]
211 		**
212 		**	shll	$2,r0,r0   \	moval	_foo[r0]
213 		**	movab	_foo[r0]   /
214 		*/
215 		register struct	node	*pf;
216 		register struct	node	*pn;
217 		register int	shfrom, shto;
218 		long	shcnt;
219 		char	*regfrom;
220 
221 		splitrand(p);
222 		if (regs[RT1][0] != '$') {
223 			if(isreg(regs[RT1]) < 0) goto std; /* alignment */
224 			if (regs[RT2][0] != '$') goto std;
225 			if (getnum(&regs[RT2][1]) != 1) goto std;
226 			r = isreg(regs[RT3]);
227 			if (r < 0 || r >= NUSE) goto std;
228 			if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std;
229 			if (uses[r] && uses[r] != pf) goto std;
230 			splitrand(pf);
231 			if (r == isreg(regs[RT1])) cp2 = regs[RT2];
232 			else if (r == isreg(regs[RT2])) cp2 = regs[RT1];
233 			else goto std;
234 			if (*cp2 == '$') goto std;
235 			if ((pn = pf->forw)->op != CBR) goto std;
236 			if (pn->subop != JEQ && pn->subop != JNE) goto std;
237 			delnode(p); delnode(pf);
238 			pn->subop = (pn->subop == JEQ) ? JBC : JBS;
239 			for(cp1=p->code; *cp1++!=',';);
240 			while (*cp1++= *cp2++);
241 			pn->code = p->code; pn->pop = NULL;
242 			uses[r] = NULL;
243 			nbj++;
244 			p = pn;
245 			goto std;
246 		}
247 		if ((shcnt = getnum(&regs[RT1][1])) < 1 || shcnt > 2) goto std;
248 		if ((shfrom = isreg(regs[RT2])) >= 0)
249 			regfrom = copy(regs[RT2]);
250 		if ((shto = isreg(regs[RT3])) >= 0 && shto<NUSE)
251 		{
252 			int	regnum;
253 
254 			if (uses[shto] != (pf = p->forw)) goto ashadd;
255 			if (pf->op != MOVA && pf->op != PUSHA) goto ashadd;
256 			if (pf->subop != BYTE) goto ashadd;
257 			splitrand(pf);
258 			if (!indexa(regs[RT1])) goto std;
259 			cp2 = regs[RT1];
260 			if(!isstatic(cp2)) goto std;
261 			while (*cp2++ != '[') ;
262 			if (*cp2++ != 'r' || !isdigit(*cp2)) goto std;
263 			regnum = *cp2++ - '0';
264 			if (isdigit(*cp2))
265 			{
266 				if (cp2[1] != ']') goto std;
267 				regnum *= 10; regnum += *cp2 - '0';
268 			}
269 			if (regnum != shto) goto std;
270 			if (shfrom >= 0)	/* shll $N,r*,r0 */
271 			{
272 				delnode(p);
273 				p = pf;
274 				if (shfrom != shto)
275 				{
276 					uses[shto] = NULL; splitrand(pf);
277 					cp2=regs[RT1]; while (*cp2++!='[');
278 					cp1=regfrom; while (*cp2++= *cp1++);
279 					cp2[-1] = ']'; *cp2 = 0;
280 					newcode(pf);
281 				}
282 			}
283 			else
284 			{
285 				p->op = MOV; splitrand(p);
286 				strcpy(regs[RT1], regs[RT2]);
287 				strcpy(regs[RT2], regs[RT3]);
288 				regs[RT3][0] = '\0';
289 				p->pop = 0; newcode(p);
290 			}
291 			switch (shcnt)
292 			{
293 			case 1:	pf->subop = WORD; break;
294 			case 2:	pf->subop = LONG; break;
295 			}
296 			redunm++; nsaddr++;
297 		}
298 		goto std;
299 ashadd:
300 		/* at this point, RT2 and RT3 are guaranteed to be simple regs*/
301 		if (shcnt == 1) {
302 			/*
303 			** quickie:
304 			**	shll	$1,A,A	>	addl2	A,A
305 			**	shll	$1,A,B	>	addl3	A,A,B
306 			*/
307 			p->op = ADD;
308 			strcpy(regs[RT1], regs[RT2]);
309 			if(equstr(regs[RT2], regs[RT3])) {
310 				p->subop = U(LONG,OP2);
311 				regs[RT3][0] = '\0';
312 			} else
313 				p->subop = U(LONG,OP3);
314 			p->pop = 0;
315 			newcode(p);
316 		}
317 		goto std;
318 	}
319 
320 	case SHAR:
321 	case SHR:
322 	{
323 		/* bit tests:
324 		**	shrl	A,B,rC     \
325 		**	bitl	$1,rC	    >	jbc	A,B,D
326 		**	jeql	D	   /
327 		*/
328 		register struct	node	*pf;	/* forward node */
329 		register struct	node	*pn;	/* next node (after pf) */
330 		register int	extreg;		/* reg extracted to */
331 
332 		splitrand(p);
333 		if(isreg(regs[RT1]) < 0) goto std; /* alignment */
334 		extreg = isreg(regs[RT3]);
335 		if (extreg < 0 || extreg >= NUSE) goto std;
336 		if ((pf = p->forw)->op != BIT) goto std;
337 		if (uses[extreg] && uses[extreg] != pf) goto std;
338 		splitrand(pf);
339 		if (regs[RT1][0] != '$') goto std;
340 		if (getnum(&regs[RT1][1]) != 1) goto std;
341 		if (extreg != isreg(regs[RT2])) goto std;
342 		if ((pn = pf->forw)->op != CBR) goto std;
343 		if (pn->subop != JEQ && pn->subop != JNE) goto std;
344 		delnode(p); delnode(pf);
345 		pn->subop = (pn->subop == JEQ) ? JBC : JBS;
346 		for(cp1=p->code; *cp1++!=',';);
347 		while (*cp1!=',') cp1++; *cp1='\0';
348 		pn->code = p->code; pn->pop = NULL;
349 		uses[extreg] = NULL; nbj++;
350 		p = pn;
351 		goto std;
352 	}
353 
354 	case AND:
355 	{
356 		/* unsigned conversion:
357 		**	cvtbl	A,B;	andl2	$255,B > movzbl	A,B
358 		**
359 		** also byte- and word-size fields:
360 		**	shrl	$(3-n)*8,A,B; andl2	$255,B	>	movzbl	n+A,B
361 		**	shrl	$(1-n)*16,A,B; andl2	$65535,B >	movzwl	n+A,B
362 		*/
363 		char src[C2_ASIZE];
364 		register int f;	/* field length */
365 		register struct	node	*pb = p->back;	/* backward node */
366 
367 		if (p->subop != U(LONG,OP2))
368 			goto std;
369 		splitrand(p); cp1=regs[RT1];
370 		if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff)
371 			goto std;
372 		f = f==0xff ? 8 : 16;
373 		if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR)
374 			goto std;
375 		/* save source of ANDL in 'src' */
376 		strcpy(src, regs[RT2]);
377 		splitrand(pb);
378 		if (!equstr(src,lastrand))
379 			goto std;
380 		if (pb->op==CVT || pb->op==MOVZ) {
381 			if (!(bitsize[pb->subop&0xF]==f
382 			  && bitsize[pb->subop>>4]>=f)) /* good CVT */
383 				goto std;
384 			strcpy(src, regs[RT1]);
385 		} else {
386 			register int	boff;	/* bit offset */
387 
388 			if (regs[RT1][0] != '$') goto std;
389 			if ((boff = getnum(&regs[RT1][1])) < 0) goto std;
390 			if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std;
391 			if ((boff & (f-1)) != 0) goto std;
392 			boff = (32-boff-f) / 8;
393 			if (boff == 0)
394 				strcpy(src, regs[RT2]);
395 			else
396 				sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+",
397 					regs[RT2]);
398 		}
399 		delnode(pb);
400 		p->op = MOVZ;
401 		p->subop = U((f==8 ? BYTE : WORD), LONG);
402 		sprintf(line,"%s,%s",src,lastrand);
403 		p->pop=0;
404 		p->code = copy(line);
405 		goto std;
406 	}
407 
408 	case CMP:
409 	{
410 		/* comparison to -63 to -1:
411 		**	cmpl	r0,$-1	>	incl	r0
412 		**	jeql	...
413 		**
414 		**	cmpl	r0,$-63	>	addl2	$63,r0
415 		**	jeql	...
416 		*/
417 		register int	num;
418 		register int	reg;
419 		register struct	node	*regp = p->back;
420 
421 		if (p->forw->op != CBR) goto std;
422 		if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std;
423 		splitrand(p);
424 		if (strncmp(regs[RT2], "$-", 2) != 0) goto std;
425 		reg = r = isreg(regs[RT1]);
426 		if (r < 0) goto std;
427 		if (r < NUSE && uses[r] != 0) goto std;
428 		if (r >= NUSE && regp->op == MOV && p->subop == regp->subop)
429 		{
430 			if (*regp->code != 'r') goto std;
431 			reg = regp->code[1] - '0';
432 			if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg])
433 				goto std;
434 		}
435 		if (r >= NUSE) goto std;
436 		if (reg != r)
437 			sprintf(regs[RT1], "r%d", reg);
438 		if ((num = getnum(&regs[RT2][2])) <= 0 || num > 63) goto std;
439 		if (num == 1)
440 		{
441 			p->op = INC; regs[RT2][0] = '\0';
442 		}
443 		else
444 		{
445 			register char	*t;
446 
447 			t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t;
448 			p->op = ADD; p->subop = U(p->subop, OP2);
449 			for (t = &regs[RT1][2]; t[-1] = *t; t++) ;
450 		}
451 		p->pop = 0; newcode(p);
452 		goto std;
453 	}
454 
455 	case JBR: case JMP:
456 		clearuse();
457 		if ((p->subop&0xF)==RET) {
458 			switch((p->subop>>4)&0xF) {
459 				case 2: uses[1]=p; regs[1][0]= -1;
460 				case 1: uses[0]=p; regs[0][0]= -1;
461 			}
462 			break;
463 		}
464 		if (p->ref==0) goto std;	/* jmp (r0) */
465 		/* fall through */
466 	case CBR:
467 		if (p->ref->ref!=0) {
468 			for (r=NUSE;--r>=0;)
469 				if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;}
470 			if ((1<<NUSE) & (int)p->ref->ref) useacc=p;
471 		}
472 		break;
473 	case LNF:
474 		/* lnf a; addf b ==> ldf b; subf a */
475 		{ register struct node	*pf = p->forw;
476 		if(pf->op==ADDF && p->subop==pf->subop) {
477 			p->op = LDF;
478 			p->pop = 0;
479 			pf->op = SUBF;
480 			pf->pop = 0;
481 			cp1 = p->code;
482 			p->code = pf->code;
483 			pf->code = cp1;
484 			p = pf->forw;
485 			break;
486 		}}
487 	case LDF: case LDFD: case CVLF: /* destroy acc */
488 		useacc = 0;
489 		goto std;
490 	case STF:
491 		{ register struct node	*pf;
492 		if((pf=flops(p)) != p) {
493 			p = pf; /* usually p->forw; */
494 			break;
495 		}}
496 		if(ldmov(p)) {
497 			p = p->forw;
498 			break;
499 		}
500 		if(useacc == 0)
501 			useacc = p;
502 		goto std;
503 	case ADDF: case MULF: /* commutatives - create clients for flops */
504 		/* stf a; ldf b; addf a => stf a; ldf a; addf b */
505 		{ register struct node	*pb = p->back;
506 		register struct node	*pbb = pb->back;
507 		if(pb->op==LDF && pb->subop==p->subop &&
508 		 pbb && pbb->op==STF && pbb->subop==p->subop &&
509 		 equstr(pbb->code, p->code)) {
510 			cp1 = p->code;
511 			p->code = pb->code;
512 			pb->code = cp1;
513 		}}
514 	/* use acc and regs */
515 	case CMPF: case CVFL: case SUBF: case DIVF:
516 		if(useacc == 0)
517 			useacc = p;
518 		goto std;
519 	case TSTF:
520 		break;
521 	case PUSHD:
522 		if(ldmov(p)) {
523 			p = p->forw;
524 			break;
525 		}
526 	case CVDF: case NEGF: /* use only acc */
527 	case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF:
528 		if(useacc == 0)
529 			useacc = p;
530 	case EROU: case JSW:
531 	case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ;
532 	}
533 	}
534 	for (p= &first; p!=0; p=p->forw)
535 		if (p->op==LABEL || p->op==DLABEL) p->ref=0;	/* erase our tracks */
536 }
537 
538 char *
539 byondrd(p) register struct node *p; {
540 /* return pointer to register which is "beyond last read/modify operand" */
541 	if (OP2==(p->subop>>4)) return(regs[RT3]);
542 	switch (p->op) {
543 		case MFPR:
544 		case PUSHA:
545 		case TST: case INC: case DEC: case PUSH:
546 		case LDF: case LNF: case CVLF: case LDFD:
547 		case ADDF: case SUBF: case MULF: case DIVF:
548 		case CMPF:
549 			return(regs[RT2]);
550 		case MTPR:
551 #ifndef EMOD
552 		case EDIV:
553 #endif EMOD
554 		case CBR: /* must be JBC/JBS */
555 		case BIT: case CMP: case CALLS:	case CALLF:
556 		case CMPF2:
557 			return(regs[RT3]);
558 		case EMUL:
559 		case PROBE:
560 		case MOVBLK:
561 		case CASE:
562 			return(regs[RT4]);
563 	}
564 	return(lastrand);
565 }
566 
567 struct node *
568 bflow(p)
569 register struct node *p;
570 {
571 	register char *cp1,*cp2,**preg;
572 	register int r, fr, dblflg=0;
573 	int flow= -1;
574 	struct node *olduse=0, *olduse1=0;
575 
576 	if(p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4)
577 		dblflg |= 1;	/* double dest */
578 	if((p->subop&0xF)==DOUBLE || p->subop==QUAD)
579 		dblflg |= 2;	/* double src */
580 	splitrand(p);
581 	if (p->op!=PUSH
582 #ifndef EMOD
583 	&& p->op!=EDIV
584 #endif EMOD
585 	&& p->op!=EMUL
586 	&& p->subop && 0<=(r=isreg(lastrand)) && r<NUSE && uses[r]==p->forw) {
587 	if (equtype(p->subop,regs[r][0])
588 	|| ((p->op==CVT || p->op==MOVZ || p->op==CVFL)
589 			 && 0xf&regs[r][0] && compat(0xf&(p->subop>>4),regs[r][0]))
590 	|| p->op==MOVA && compat(LONG, regs[r][0])) {
591 		register int r2;
592 		if (regs[r][1]!=0) {/* send directly to destination */
593 			if (p->op==INC || p->op==DEC) {
594 				if (p->op==DEC) p->op=SUB; else p->op=ADD;
595 				p->subop=(OP2<<4)+(p->subop&0xF); /* use 2 now, convert to 3 later */
596 				p->pop=0;
597 				cp1=lastrand; cp2=regs[RT2]; while (*cp2++= *cp1++); /* copy reg */
598 				cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0;
599 			}
600 			cp1=regs[r]+1; cp2=lastrand;
601 			if (OP2==(p->subop>>4)) {/* use 3 operand form of instruction */
602 				p->pop=0;
603 				p->subop += (OP3-OP2)<<4; lastrand=cp2=regs[RT3];
604 			}
605 			while (*cp2++= *cp1++);
606 			if (p->op==MOVA && p->forw->op==PUSH) {
607 				p->op=PUSHA;
608 				*regs[RT2]=0; p->pop=0;
609 			} else if ((p->op==MOV || p->op==CVT) && p->forw->op==PUSH) {
610 				p->op=PUSH; p->subop &= 0xF;
611 				*regs[RT2]=0; p->pop=0;
612 			}
613 			delnode(p->forw);
614 			if (0<=(r2=isreg(lastrand)) && r2<NUSE) {
615 				uses[r2]=uses[r]; uses[r]=0;
616 			}
617 			redun3(p);
618 			newcode(p); redunm++; flow=r;
619 		} else if (p->op==MOV) {
620 			/* superfluous fetch */
621 			int nmatch;
622 			char src[C2_ASIZE];
623 	movit:
624 			cp2=src; cp1=regs[RT1]; while (*cp2++= *cp1++);
625 			splitrand(p->forw);
626 			if (p->forw->op != INC && p->forw->op != DEC)
627 				lastrand=byondrd(p->forw);
628 			nmatch=0;
629 			for (preg=regs+RT1;*preg!=lastrand;preg++)
630 				if (r==isreg(*preg)) {
631 				cp2= *preg; cp1=src; while (*cp2++= *cp1++); ++nmatch;
632 				}
633 			if (nmatch==1) {
634 				if (OP2==(p->forw->subop>>4) && equstr(src,regs[RT2])) {
635 					p->forw->pop=0;
636 					p->forw->subop += (OP3-OP2)<<4; cp1=regs[RT3];
637 					*cp1++='r'; *cp1++=r+'0'; *cp1=0;
638 				}
639 				delnode(p); p=p->forw;
640 				if (0<=(r2=isreg(src)) && r2<NUSE) {
641 					uses[r2]=uses[r]; uses[r]=0;
642 				}
643 				redun3(p);
644 				newcode(p); redunm++; flow=r;
645 			} else splitrand(p);
646 		}
647 	} else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ)
648 		&& p->forw->subop&0xf 	/* if base or index, then forget it */
649 		&& compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1]))
650 			goto movit;
651 	}
652 	/* adjust 'lastrand' past any 'read' or 'modify' operands. */
653 	lastrand=byondrd(p);
654 	/* a 'write' clobbers the register. */
655 	if (0<=(r=isreg(lastrand)) && r<NUSE
656 	|| OP2==(p->subop>>4) && 0<=(r=isreg(regs[RT2])) && r<NUSE && uses[r]==0) {
657 		/* writing a dead register is useless, but watch side effects */
658 		switch (p->op) {
659 #ifndef EMOD
660 		case EDIV:
661 #endif EMOD
662 		case EMUL:
663 		case AOBLEQ: case AOBLSS: break;
664 		default:
665 			if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) {
666 			/* no direct uses, check for use of condition codes */
667 				register struct node *q=p;
668 				while ((q=nonlab(q->forw))->op==JBR && q->subop==0) q=q->ref;	/* cc unused, unchanged */
669 				if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) {/* ... and destroyed */
670 					preg=regs+RT1;
671 					while (cp1= *preg++) {
672 						if ((cp1==lastrand)  &&
673 						    (p->op != CLR) &&
674 						    (p->op != CVFL))
675 						{redunm++; delnode(p); return(p->forw);}
676 						if (equstr(cp1,lastrand)) break;
677 					}
678 				}
679 			}
680 			flow=r;
681 		}
682 	}
683 	if (0<=(r=flow)) {
684 		olduse=uses[r]; uses[r]=0; *(short *)(regs[r])=0;
685 		/* if r0 destroyed, dont keep r1 */
686 		if(dblflg&1) {
687 			olduse1=uses[++r]; uses[r]=0; *(short *)(regs[r])=0;
688 		}
689 	}
690 	/* now look for 'read' or 'modify' (read & write) uses */
691 	preg=regs+RT1;
692 	while (*(cp1= *preg++)) {
693 		/* check for  r  */
694 		if (lastrand!=cp1 && 0<=(r=isreg(cp1)) && r<NUSE && (uses[r]==0)){
695 			uses[r]=p; cp2=regs[r]; *cp2++=p->subop;
696 			if((p->op==SHAL || p->op==SHAR || p->op==SHL || p->op==SHR)
697 				 && cp1==regs[RT1]) cp2[-1]=BYTE;
698 			if(p->op==CBR && (p->subop==JBC || p->subop==JBS)) cp2[-1]=LONG;
699 			if(p->op==MOVA && cp1==regs[RT2]) cp2[-1]=LONG;
700 			/* ediv/emod's 2nd operand is quad */
701 			if(((p->op==EDIV
702 #ifdef EMOD
703 			|| p->op==EMOD
704 #endif EMOD
705 			) && cp1==regs[RT2] || (dblflg&2))
706 			 && ++r<NUSE && uses[r]==0) {
707 				*cp2=0;
708 				uses[r]=p; cp2=regs[r]; *cp2++=p->subop;
709 			}
710 			if(p->op==MOV || p->op==PUSH || p->op==CVT ||
711 			 p->op==MOVZ || p->op==COM || p->op==NEG || p->op==STF) {
712 				if (p->op==PUSH) cp1="-(sp)";
713 				else {
714 					cp1=regs[RT2];
715 					if (0<=(r=isreg(cp1)) && r<NUSE) {
716 						/* reincarnation!! */
717 					/* as in  addl2 r0,r1;  movl r1,r0;  ret  */
718 						if(uses[r]==0)
719 							uses[r]=olduse;
720 						if((dblflg&1) && uses[r+1]==0)
721 							uses[r+1]=olduse1;
722 					}
723 					if (p->op!=MOV) cp1=0;
724 				}
725 				if (cp1) while (*cp2++= *cp1++);
726 				else *cp2=0;
727 			} else *cp2=0;
728 			continue;
729 		}
730 		/* check for (r),[r] */
731 		do if (*cp1=='(' || *cp1=='[') {/* get register number */
732 			char t;
733 			cp2= ++cp1; while (*++cp1!=')' && *cp1!=']'); t= *cp1; *cp1=0;
734 			if (0<=(r=isreg(cp2)) && r<NUSE && (uses[r]==0 || uses[r]==p)) {
735 				uses[r]=p; regs[r][0]=(*--cp2=='[' ? OPX<<4 : OPB<<4);
736 			}
737 			*cp1=t;
738 		} while (*++cp1);
739 	}
740 #ifdef MOVAFASTER
741 	/* pushax or movax possibility? */
742 	cp1=regs[RT1];
743 	if (*cp1++=='$' && isstatic(cp1)) {
744 		if (p->op==MOV && p->subop==LONG) {
745 			if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) {
746 				cp1=p->code; while (*cp1++!=','); p->code= --cp1;
747 			}
748 			p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0;
749 		} else if (p->op==PUSH && p->subop==LONG) {
750 			p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0;
751 		} else if (p->op==ADD && p->subop==U(LONG,OP3)
752 				 && 0<=(r=isreg(regs[RT2]))) {
753 			cp1=cp2=p->code; ++cp1;
754 			do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='[';
755 			do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']';
756 			if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;}
757 			else {p->op = PUSHA; p->subop = BYTE; *cp2=0;}
758 			if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;}
759 			p->pop=0;
760 		}
761 	}
762 #endif MOVAFASTER
763 	return(p);
764 }
765 
766 /* try to eliminate STF's */
767 struct node *
768 flops(q)
769 register struct node *q;
770 {
771 	register struct node *p;
772 	register int r;
773 
774 	if(!(q->op==STF && ((r=isreg(q->code))<NUSE) && r>=0))
775 		return(q);
776 	if(uses[r]) {
777 		/* see if anyone destroys acc between us */
778 		for(p=q->forw; p!=uses[r]; p=p->forw)
779 			switch(p->op) {
780 			case LABEL:
781 			case LDF: case LNF: case CVLF: case LDFD:
782 			case CVDF: case NEGF: case ADDF: case SUBF:
783 			case MULF: case DIVF: case SINF: case COSF:
784 			case ATANF: case LOGF: case SQRTF: case EXPF:
785 				return(q);
786 			}
787 
788 		if(q->subop == p->subop)
789 			switch(p->op) {	/* do it in the accumulator */
790 			case LDF:	/* redundant load */
791 				delnode(p); nld++;
792 				p = p->forw;
793 				break;
794 			case LNF: /* stf r; lnf r ==> negf */
795 				p->op = NEGF;
796 				p->pop = 0;
797 				p->code = 0;
798 				break;
799 			case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */
800 				{ register char *s;
801 				register struct node *p1=p->forw;
802 				for(s=p->code; *s!=','; s++);
803 				*s = 0;
804 				if(isreg(p->code) == r)
805 					p->code = s+1;
806 				else {
807 					if(p1->op != CBR || isreg(s+1) != r) {
808 						*s = ',';
809 						return(q);
810 					}
811 					if(p1->subop > JNE) {
812 						p1->subop ^= 1;
813 						p1->pop = 0;
814 						nrevbr++;
815 					}
816 				}
817 				p->op = CMPF;
818 				p->pop = 0;
819 				}
820 				break;
821 			default:
822 				return(q);
823 			}
824 		else if(p->subop==LONG) {
825 			switch(p->op) {
826 			case TST:	/* stf r; tstl r ==> tstf */
827 				p->op = TSTF;
828 				p->code = 0;
829 				break;
830 			/* send directly to destination */
831 			case MOV:	/* stf r; movl r,x ==> stf x */
832 			case PUSH:	/* stf r; pushl r ==> stf -(sp)/pushd */
833 				if(q->subop == DOUBLE) {
834 					register struct node *b = p->back;
835 					/* assume b's 2nd arg is ok */
836 					if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG))
837 						return(q);
838 					delnode(b); redunm++;
839 				}
840 				if(p->op==PUSH) {
841 					if(q->subop == DOUBLE) {
842 						p->op = PUSHD;
843 						p->code = 0;
844 					} else {
845 						p->op = q->op;
846 						p->code = copy("-(sp)");
847 					}
848 				} else {
849 					p->op = q->op;
850 					while(*p->code++ != ',');
851 				}
852 				break;
853 			default:
854 				return(q);
855 			}
856 			p->pop = 0;
857 			p->subop = q->subop;
858 		} else
859 			return(q);
860 		uses[r] = 0;
861 		if(q->subop == DOUBLE)
862 			uses[r+1] = 0;
863 		{ /* undo any effect on uses in the area between p and q,
864 		   * as we are going over it again */
865 			register struct node *b;
866 			for(b=p; b!=q; b=b->back) {
867 				for(r=0; r<NUSE; r++) {
868 					if(uses[r] == b)
869 						uses[r] = 0;
870 					if(useacc == b)
871 						useacc = 0;
872 				}
873 			}
874 		}
875 		return(p->forw); /* make p the next for bflow */
876 	}
877 	/* it's a store to reg which isnt used elsewhere */
878 	if((p=q->forw)->op == CBR) {
879 		q->op = TSTF;
880 		q->pop = 0;
881 		q->code = 0;
882 	} else {
883 		delnode(q); nst++;
884 		if(p->op ==STF || p->op==TSTF || p->op==PUSHD) {
885 			if(useacc == p)
886 				useacc = 0;
887 			return(p->forw);	/* so ldmov can be used on p */
888 		}
889 	}
890 	return(p);
891 }
892 
893 /* try to change load/store sequences to movl */
894 ldmov(q)
895 register struct node *q;
896 {
897 	register struct node *p;
898 	register char *s, *pcod, *cp;
899 	char *dlsw();
900 
901 	p = q->back;
902 	if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD)
903 	 && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE))))
904 		return(0);
905 	pcod = p->code;
906  	cp = p->code;
907 	/* prepare args for movl/pushl */
908 	if(q->op!=TSTF && q->subop==DOUBLE) {
909 		if(p->op == LDF) {
910 			if((s = dlsw(p->code)) == NULL)
911 				return(0);
912 
913 			strcpy(line, s);
914 			if(q->op == STF) {
915 				strcat(line, ",");
916 				if((s = dlsw(q->code)) == NULL)
917 					return(0);
918 				strcat(line, s);
919 				p->op = MOV;
920 			} else
921 				p->op = PUSH;
922 		} else { /* LDFD */
923 			if(q->op == STF) {
924 				if((s = dlsw(q->code)) == NULL)
925 					return(0);
926 			} else
927 				s = "-(sp)";
928 			strcpy(line, s);
929 			p->op = CLR;
930 		}
931 		p->pop = 0;
932 		p->subop = LONG;
933 		p->code = copy(line);
934 	} else
935 		{
936  		if ((p->op == LDF) && (p->subop == DOUBLE) &&
937  	           (indexa(cp)))  return(0);
938 		delnode(p);
939 		}
940 	strcpy(line, pcod);
941 	if(q->op == STF) {	/* ldf x; stf y ==> movl x,y */
942 		strcat(line, ",");
943 		strcat(line, q->code);
944 		q->op = MOV;
945 		nst++;
946 	} else if(q->op == TSTF)	/* ldf x; tstf ==> tstl x */
947 		q->op = TST;
948 	else	/* ldd x; pushd ==> pushl x+4; pushl x */
949 		q->op = PUSH;
950 	q->pop = 0;
951 	q->subop = LONG;
952 	q->code = copy(line);
953 	nld++;
954 	return(1);
955 }
956 
957 /* reconstruct the address of l.s.w. of a double operand */
958 char *
959 dlsw(d)
960 	register char *d;
961 {
962 	register char *s, *t, *c;
963 	register int r;
964 	static char lsw[C2_ASIZE];
965 
966 	if(d[0] == '*' || d[0] == '$')
967 		return(NULL);
968 	if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2]))
969 		return(NULL);
970 	t = lsw;
971 	if((r=isreg(d)) >= 0)
972 		sprintf(t, "r%d", r+1);
973 	else {
974 		for(s=d; *s && *s!='('; *t++ = *s++)
975 			if(*s == '[')
976 				return(NULL);
977 		if(s!=d)
978 			*t++ = '+';
979 		*t++ = '4';
980 		while(*t++ = *s)
981 			if(*s++ == '[' )
982 			{
983 				return(NULL);
984 			}
985 	}
986 	return(lsw);
987 }
988 checkexpr(p)
989 register char *p;
990 {
991 
992 	while(*p && *p != ','){
993 	if ((*p == '+' ) || (*p == '-'))
994 		return(1);
995 	*p++;
996 	}
997 	return(0);
998 }
999