xref: /inferno-os/utils/qc/peep.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include "gc.h"
2 
3 void
4 peep(void)
5 {
6 	Reg *r, *r1, *r2;
7 	Prog *p, *p1;
8 	int t;
9 /*
10  * complete R structure
11  */
12 	t = 0;
13 	for(r=firstr; r!=R; r=r1) {
14 		r1 = r->link;
15 		if(r1 == R)
16 			break;
17 		p = r->prog->link;
18 		while(p != r1->prog)
19 		switch(p->as) {
20 		default:
21 			r2 = rega();
22 			r->link = r2;
23 			r2->link = r1;
24 
25 			r2->prog = p;
26 			r2->p1 = r;
27 			r->s1 = r2;
28 			r2->s1 = r1;
29 			r1->p1 = r2;
30 
31 			r = r2;
32 			t++;
33 
34 		case ADATA:
35 		case AGLOBL:
36 		case ANAME:
37 		case ASIGNAME:
38 			p = p->link;
39 		}
40 	}
41 
42 loop1:
43 	t = 0;
44 	for(r=firstr; r!=R; r=r->link) {
45 		p = r->prog;
46 		if(p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
47 		if(regtyp(&p->to)) {
48 			if(regtyp(&p->from))
49 			if(p->from.type == p->to.type) {
50 				if(copyprop(r)) {
51 					excise(r);
52 					t++;
53 				} else
54 				if(subprop(r) && copyprop(r)) {
55 					excise(r);
56 					t++;
57 				}
58 			}
59 			if(regzer(&p->from))
60 			if(p->to.type == D_REG) {
61 				p->from.type = D_REG;
62 				p->from.reg = REGZERO;
63 				if(copyprop(r)) {
64 					excise(r);
65 					t++;
66 				} else
67 				if(subprop(r) && copyprop(r)) {
68 					excise(r);
69 					t++;
70 				}
71 			}
72 		}
73 	}
74 	if(t)
75 		goto loop1;
76 	/*
77 	 * look for MOVB x,R; MOVB R,R
78 	 */
79 	for(r=firstr; r!=R; r=r->link) {
80 		p = r->prog;
81 		switch(p->as) {
82 		default:
83 			continue;
84 		case AMOVH:
85 		case AMOVHZ:
86 		case AMOVB:
87 		case AMOVBZ:
88 			if(p->to.type != D_REG)
89 				continue;
90 			break;
91 		}
92 		r1 = r->link;
93 		if(r1 == R)
94 			continue;
95 		p1 = r1->prog;
96 		if(p1->as != p->as)
97 			continue;
98 		if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
99 			continue;
100 		if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
101 			continue;
102 		excise(r1);
103 	}
104 
105 	if(debug['Q'] > 1)
106 		return;	/* allow following code improvement to be suppressed */
107 
108 	/*
109 	 * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
110 	 * when OP can set condition codes correctly
111 	 */
112 	for(r=firstr; r!=R; r=r->link) {
113 		p = r->prog;
114 		switch(p->as) {
115 		case ACMP:
116 			if(!regzer(&p->to))
117 				continue;
118 			r1 = r->s1;
119 			if(r1 == R)
120 				continue;
121 			switch(r1->prog->as) {
122 			default:
123 				continue;
124 			case ABCL:
125 			case ABC:
126 				/* the conditions can be complex and these are currently little used */
127 				continue;
128 			case ABEQ:
129 			case ABGE:
130 			case ABGT:
131 			case ABLE:
132 			case ABLT:
133 			case ABNE:
134 			case ABVC:
135 			case ABVS:
136 				break;
137 			}
138 			r1 = r;
139 			do
140 				r1 = uniqp(r1);
141 			while (r1 != R && r1->prog->as == ANOP);
142 			if(r1 == R)
143 				continue;
144 			p1 = r1->prog;
145 			if(p1->to.type != D_REG || p1->to.reg != p->from.reg)
146 				continue;
147 			switch(p1->as) {
148 			case ASUB:
149 			case AADD:
150 			case AXOR:
151 			case AOR:
152 				/* irregular instructions */
153 				if(p1->from.type == D_CONST)
154 					continue;
155 				break;
156 			}
157 			switch(p1->as) {
158 			default:
159 				continue;
160 			case AMOVW:
161 				if(p1->from.type != D_REG)
162 					continue;
163 				continue;
164 			case AANDCC:
165 			case AANDNCC:
166 			case AORCC:
167 			case AORNCC:
168 			case AXORCC:
169 			case ASUBCC:
170 			case ASUBECC:
171 			case ASUBMECC:
172 			case ASUBZECC:
173 			case AADDCC:
174 			case AADDCCC:
175 			case AADDECC:
176 			case AADDMECC:
177 			case AADDZECC:
178 			case ARLWMICC:
179 			case ARLWNMCC:
180 				t = p1->as;
181 				break;
182 			/* don't deal with floating point instructions for now */
183 /*
184 			case AFABS:	t = AFABSCC; break;
185 			case AFADD:	t = AFADDCC; break;
186 			case AFADDS:	t = AFADDSCC; break;
187 			case AFCTIW:	t = AFCTIWCC; break;
188 			case AFCTIWZ:	t = AFCTIWZCC; break;
189 			case AFDIV:	t = AFDIVCC; break;
190 			case AFDIVS:	t = AFDIVSCC; break;
191 			case AFMADD:	t = AFMADDCC; break;
192 			case AFMADDS:	t = AFMADDSCC; break;
193 			case AFMOVD:	t = AFMOVDCC; break;
194 			case AFMSUB:	t = AFMSUBCC; break;
195 			case AFMSUBS:	t = AFMSUBSCC; break;
196 			case AFMUL:	t = AFMULCC; break;
197 			case AFMULS:	t = AFMULSCC; break;
198 			case AFNABS:	t = AFNABSCC; break;
199 			case AFNEG:	t = AFNEGCC; break;
200 			case AFNMADD:	t = AFNMADDCC; break;
201 			case AFNMADDS:	t = AFNMADDSCC; break;
202 			case AFNMSUB:	t = AFNMSUBCC; break;
203 			case AFNMSUBS:	t = AFNMSUBSCC; break;
204 			case AFRSP:	t = AFRSPCC; break;
205 			case AFSUB:	t = AFSUBCC; break;
206 			case AFSUBS:	t = AFSUBSCC; break;
207 			case ACNTLZW:	t = ACNTLZWCC; break;
208 			case AMTFSB0:	t = AMTFSB0CC; break;
209 			case AMTFSB1:	t = AMTFSB1CC; break;
210 */
211 			case AADD:	t = AADDCC; break;
212 			case AADDV:	t = AADDVCC; break;
213 			case AADDC:	t = AADDCCC; break;
214 			case AADDCV:	t = AADDCVCC; break;
215 			case AADDME:	t = AADDMECC; break;
216 			case AADDMEV:	t = AADDMEVCC; break;
217 			case AADDE:	t = AADDECC; break;
218 			case AADDEV:	t = AADDEVCC; break;
219 			case AADDZE:	t = AADDZECC; break;
220 			case AADDZEV:	t = AADDZEVCC; break;
221 			case AAND:	t = AANDCC; break;
222 			case AANDN:	t = AANDNCC; break;
223 			case ADIVW:	t = ADIVWCC; break;
224 			case ADIVWV:	t = ADIVWVCC; break;
225 			case ADIVWU:	t = ADIVWUCC; break;
226 			case ADIVWUV:	t = ADIVWUVCC; break;
227 			case AEQV:	t = AEQVCC; break;
228 			case AEXTSB:	t = AEXTSBCC; break;
229 			case AEXTSH:	t = AEXTSHCC; break;
230 			case AMULHW:	t = AMULHWCC; break;
231 			case AMULHWU:	t = AMULHWUCC; break;
232 			case AMULLW:	t = AMULLWCC; break;
233 			case AMULLWV:	t = AMULLWVCC; break;
234 			case ANAND:	t = ANANDCC; break;
235 			case ANEG:	t = ANEGCC; break;
236 			case ANEGV:	t = ANEGVCC; break;
237 			case ANOR:	t = ANORCC; break;
238 			case AOR:	t = AORCC; break;
239 			case AORN:	t = AORNCC; break;
240 			case AREM:	t = AREMCC; break;
241 			case AREMV:	t = AREMVCC; break;
242 			case AREMU:	t = AREMUCC; break;
243 			case AREMUV:	t = AREMUVCC; break;
244 			case ARLWMI:	t = ARLWMICC; break;
245 			case ARLWNM:	t = ARLWNMCC; break;
246 			case ASLW:	t = ASLWCC; break;
247 			case ASRAW:	t = ASRAWCC; break;
248 			case ASRW:	t = ASRWCC; break;
249 			case ASUB:	t = ASUBCC; break;
250 			case ASUBV:	t = ASUBVCC; break;
251 			case ASUBC:	t = ASUBCCC; break;
252 			case ASUBCV:	t = ASUBCVCC; break;
253 			case ASUBME:	t = ASUBMECC; break;
254 			case ASUBMEV:	t = ASUBMEVCC; break;
255 			case ASUBE:	t = ASUBECC; break;
256 			case ASUBEV:	t = ASUBEVCC; break;
257 			case ASUBZE:	t = ASUBZECC; break;
258 			case ASUBZEV:	t = ASUBZEVCC; break;
259 			case AXOR:	t = AXORCC; break;
260 				break;
261 			}
262 			if(debug['Q'])
263 				print("cmp %P; %P -> ", p1, p);
264 			p1->as = t;
265 			if(debug['Q'])
266 				print("%P\n", p1);
267 			excise(r);
268 			continue;
269 		}
270 	}
271 }
272 
273 void
274 excise(Reg *r)
275 {
276 	Prog *p;
277 
278 	p = r->prog;
279 	p->as = ANOP;
280 	p->from = zprog.from;
281 	p->from3 = zprog.from3;
282 	p->to = zprog.to;
283 	p->reg = zprog.reg; /**/
284 }
285 
286 Reg*
287 uniqp(Reg *r)
288 {
289 	Reg *r1;
290 
291 	r1 = r->p1;
292 	if(r1 == R) {
293 		r1 = r->p2;
294 		if(r1 == R || r1->p2link != R)
295 			return R;
296 	} else
297 		if(r->p2 != R)
298 			return R;
299 	return r1;
300 }
301 
302 Reg*
303 uniqs(Reg *r)
304 {
305 	Reg *r1;
306 
307 	r1 = r->s1;
308 	if(r1 == R) {
309 		r1 = r->s2;
310 		if(r1 == R)
311 			return R;
312 	} else
313 		if(r->s2 != R)
314 			return R;
315 	return r1;
316 }
317 
318 /*
319  * if the system forces R0 to be zero,
320  * convert references to $0 to references to R0.
321  */
322 int
323 regzer(Adr *a)
324 {
325 	if(R0ISZERO) {
326 		if(a->type == D_CONST)
327 			if(a->sym == S)
328 				if(a->offset == 0)
329 					return 1;
330 		if(a->type == D_REG)
331 			if(a->reg == REGZERO)
332 				return 1;
333 	}
334 	return 0;
335 }
336 
337 int
338 regtyp(Adr *a)
339 {
340 
341 	if(a->type == D_REG) {
342 		if(!R0ISZERO || a->reg != REGZERO)
343 			return 1;
344 		return 0;
345 	}
346 	if(a->type == D_FREG)
347 		return 1;
348 	return 0;
349 }
350 
351 /*
352  * the idea is to substitute
353  * one register for another
354  * from one MOV to another
355  *	MOV	a, R0
356  *	ADD	b, R0	/ no use of R1
357  *	MOV	R0, R1
358  * would be converted to
359  *	MOV	a, R1
360  *	ADD	b, R1
361  *	MOV	R1, R0
362  * hopefully, then the former or latter MOV
363  * will be eliminated by copy propagation.
364  */
365 int
366 subprop(Reg *r0)
367 {
368 	Prog *p;
369 	Adr *v1, *v2;
370 	Reg *r;
371 	int t;
372 
373 	p = r0->prog;
374 	v1 = &p->from;
375 	if(!regtyp(v1))
376 		return 0;
377 	v2 = &p->to;
378 	if(!regtyp(v2))
379 		return 0;
380 	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
381 		if(uniqs(r) == R)
382 			break;
383 		p = r->prog;
384 		switch(p->as) {
385 		case ABL:
386 			return 0;
387 
388 		case AADD:
389 		case AADDC:
390 		case AADDCC:
391 		case AADDE:
392 		case AADDECC:
393 		case ASUB:
394 		case ASUBCC:
395 		case ASUBC:
396 		case ASUBCCC:
397 		case ASUBE:
398 		case ASUBECC:
399 		case ASLW:
400 		case ASLWCC:
401 		case ASRW:
402 		case ASRWCC:
403 		case ASRAW:
404 		case ASRAWCC:
405 		case AOR:
406 		case AORCC:
407 		case AORN:
408 		case AORNCC:
409 		case AAND:
410 		case AANDCC:
411 		case AANDN:
412 		case AANDNCC:
413 		case ANAND:
414 		case ANANDCC:
415 		case ANOR:
416 		case ANORCC:
417 		case AXOR:
418 		case AXORCC:
419 		case AMULHW:
420 		case AMULHWU:
421 		case AMULLW:
422 		case ADIVW:
423 		case ADIVWU:
424 		case AREM:
425 		case AREMU:
426 		case ARLWNM:
427 		case ARLWNMCC:
428 
429 		case AFADD:
430 		case AFADDS:
431 		case AFSUB:
432 		case AFSUBS:
433 		case AFMUL:
434 		case AFMULS:
435 		case AFDIV:
436 		case AFDIVS:
437 			if(p->to.type == v1->type)
438 			if(p->to.reg == v1->reg) {
439 				if(p->reg == NREG)
440 					p->reg = p->to.reg;
441 				goto gotit;
442 			}
443 			break;
444 
445 		case AADDME:
446 		case AADDMECC:
447 		case AADDZE:
448 		case AADDZECC:
449 		case ASUBME:
450 		case ASUBMECC:
451 		case ASUBZE:
452 		case ASUBZECC:
453 		case ANEG:
454 		case ANEGCC:
455 		case AFNEG:
456 		case AFNEGCC:
457 		case AFMOVS:
458 		case AFMOVD:
459 		case AMOVW:
460 			if(p->to.type == v1->type)
461 			if(p->to.reg == v1->reg)
462 				goto gotit;
463 			break;
464 		}
465 		if(copyau(&p->from, v2) ||
466 		   copyau1(p, v2) ||
467 		   copyau(&p->to, v2))
468 			break;
469 		if(copysub(&p->from, v1, v2, 0) ||
470 		   copysub1(p, v1, v2, 0) ||
471 		   copysub(&p->to, v1, v2, 0))
472 			break;
473 	}
474 	return 0;
475 
476 gotit:
477 	copysub(&p->to, v1, v2, 1);
478 	if(debug['P']) {
479 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
480 		if(p->from.type == v2->type)
481 			print(" excise");
482 		print("\n");
483 	}
484 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
485 		p = r->prog;
486 		copysub(&p->from, v1, v2, 1);
487 		copysub1(p, v1, v2, 1);
488 		copysub(&p->to, v1, v2, 1);
489 		if(debug['P'])
490 			print("%P\n", r->prog);
491 	}
492 	t = v1->reg;
493 	v1->reg = v2->reg;
494 	v2->reg = t;
495 	if(debug['P'])
496 		print("%P last\n", r->prog);
497 	return 1;
498 }
499 
500 /*
501  * The idea is to remove redundant copies.
502  *	v1->v2	F=0
503  *	(use v2	s/v2/v1/)*
504  *	set v1	F=1
505  *	use v2	return fail
506  *	-----------------
507  *	v1->v2	F=0
508  *	(use v2	s/v2/v1/)*
509  *	set v1	F=1
510  *	set v2	return success
511  */
512 int
513 copyprop(Reg *r0)
514 {
515 	Prog *p;
516 	Adr *v1, *v2;
517 	Reg *r;
518 
519 	p = r0->prog;
520 	v1 = &p->from;
521 	v2 = &p->to;
522 	if(copyas(v1, v2))
523 		return 1;
524 	for(r=firstr; r!=R; r=r->link)
525 		r->active = 0;
526 	return copy1(v1, v2, r0->s1, 0);
527 }
528 
529 int
530 copy1(Adr *v1, Adr *v2, Reg *r, int f)
531 {
532 	int t;
533 	Prog *p;
534 
535 	if(r->active) {
536 		if(debug['P'])
537 			print("act set; return 1\n");
538 		return 1;
539 	}
540 	r->active = 1;
541 	if(debug['P'])
542 		print("copy %D->%D f=%d\n", v1, v2, f);
543 	for(; r != R; r = r->s1) {
544 		p = r->prog;
545 		if(debug['P'])
546 			print("%P", p);
547 		if(!f && uniqp(r) == R) {
548 			f = 1;
549 			if(debug['P'])
550 				print("; merge; f=%d", f);
551 		}
552 		t = copyu(p, v2, A);
553 		switch(t) {
554 		case 2:	/* rar, cant split */
555 			if(debug['P'])
556 				print("; %Drar; return 0\n", v2);
557 			return 0;
558 
559 		case 3:	/* set */
560 			if(debug['P'])
561 				print("; %Dset; return 1\n", v2);
562 			return 1;
563 
564 		case 1:	/* used, substitute */
565 		case 4:	/* use and set */
566 			if(f) {
567 				if(!debug['P'])
568 					return 0;
569 				if(t == 4)
570 					print("; %Dused+set and f=%d; return 0\n", v2, f);
571 				else
572 					print("; %Dused and f=%d; return 0\n", v2, f);
573 				return 0;
574 			}
575 			if(copyu(p, v2, v1)) {
576 				if(debug['P'])
577 					print("; sub fail; return 0\n");
578 				return 0;
579 			}
580 			if(debug['P'])
581 				print("; sub%D/%D", v2, v1);
582 			if(t == 4) {
583 				if(debug['P'])
584 					print("; %Dused+set; return 1\n", v2);
585 				return 1;
586 			}
587 			break;
588 		}
589 		if(!f) {
590 			t = copyu(p, v1, A);
591 			if(!f && (t == 2 || t == 3 || t == 4)) {
592 				f = 1;
593 				if(debug['P'])
594 					print("; %Dset and !f; f=%d", v1, f);
595 			}
596 		}
597 		if(debug['P'])
598 			print("\n");
599 		if(r->s2)
600 			if(!copy1(v1, v2, r->s2, f))
601 				return 0;
602 	}
603 	return 1;
604 }
605 
606 /*
607  * return
608  * 1 if v only used (and substitute),
609  * 2 if read-alter-rewrite
610  * 3 if set
611  * 4 if set and used
612  * 0 otherwise (not touched)
613  */
614 int
615 copyu(Prog *p, Adr *v, Adr *s)
616 {
617 
618 	switch(p->as) {
619 
620 	default:
621 		if(debug['P'])
622 			print(" (?)");
623 		return 2;
624 
625 	case ANOP:	/* read, write */
626 	case AMOVW:
627 	case AMOVH:
628 	case AMOVHZ:
629 	case AMOVB:
630 	case AMOVBZ:
631 
632 	case ANEG:
633 	case ANEGCC:
634 	case AADDME:
635 	case AADDMECC:
636 	case AADDZE:
637 	case AADDZECC:
638 	case ASUBME:
639 	case ASUBMECC:
640 	case ASUBZE:
641 	case ASUBZECC:
642 
643 	case AFCTIW:
644 	case AFCTIWZ:
645 	case AFMOVS:
646 	case AFMOVD:
647 	case AFRSP:
648 	case AFNEG:
649 	case AFNEGCC:
650 		if(s != A) {
651 			if(copysub(&p->from, v, s, 1))
652 				return 1;
653 			if(!copyas(&p->to, v))
654 				if(copysub(&p->to, v, s, 1))
655 					return 1;
656 			return 0;
657 		}
658 		if(copyas(&p->to, v)) {
659 			if(copyau(&p->from, v))
660 				return 4;
661 			return 3;
662 		}
663 		if(copyau(&p->from, v))
664 			return 1;
665 		if(copyau(&p->to, v))
666 			return 1;
667 		return 0;
668 
669 	case ARLWMI:	/* read read rar */
670 	case ARLWMICC:
671 		if(copyas(&p->to, v))
672 			return 2;
673 		/* fall through */
674 
675 	case AADD:	/* read read write */
676 	case AADDC:
677 	case AADDE:
678 	case ASUB:
679 	case ASLW:
680 	case ASRW:
681 	case ASRAW:
682 	case AOR:
683 	case AORCC:
684 	case AORN:
685 	case AORNCC:
686 	case AAND:
687 	case AANDCC:
688 	case AANDN:
689 	case AANDNCC:
690 	case ANAND:
691 	case ANANDCC:
692 	case ANOR:
693 	case ANORCC:
694 	case AXOR:
695 	case AMULHW:
696 	case AMULHWU:
697 	case AMULLW:
698 	case ADIVW:
699 	case ADIVWU:
700 	case AREM:
701 	case AREMU:
702 	case ARLWNM:
703 	case ARLWNMCC:
704 
705 	case AFADDS:
706 	case AFADD:
707 	case AFSUBS:
708 	case AFSUB:
709 	case AFMULS:
710 	case AFMUL:
711 	case AFDIVS:
712 	case AFDIV:
713 		if(s != A) {
714 			if(copysub(&p->from, v, s, 1))
715 				return 1;
716 			if(copysub1(p, v, s, 1))
717 				return 1;
718 			if(!copyas(&p->to, v))
719 				if(copysub(&p->to, v, s, 1))
720 					return 1;
721 			return 0;
722 		}
723 		if(copyas(&p->to, v)) {
724 			if(p->reg == NREG)
725 				p->reg = p->to.reg;
726 			if(copyau(&p->from, v))
727 				return 4;
728 			if(copyau1(p, v))
729 				return 4;
730 			return 3;
731 		}
732 		if(copyau(&p->from, v))
733 			return 1;
734 		if(copyau1(p, v))
735 			return 1;
736 		if(copyau(&p->to, v))
737 			return 1;
738 		return 0;
739 
740 	case ABEQ:
741 	case ABGT:
742 	case ABGE:
743 	case ABLT:
744 	case ABLE:
745 	case ABNE:
746 	case ABVC:
747 	case ABVS:
748 		break;
749 
750 	case ACMP:	/* read read */
751 	case ACMPU:
752 	case AFCMPO:
753 	case AFCMPU:
754 		if(s != A) {
755 			if(copysub(&p->from, v, s, 1))
756 				return 1;
757 			return copysub(&p->to, v, s, 1);
758 		}
759 		if(copyau(&p->from, v))
760 			return 1;
761 		if(copyau(&p->to, v))
762 			return 1;
763 		break;
764 
765 	case ABR:	/* funny */
766 		if(s != A) {
767 			if(copysub(&p->to, v, s, 1))
768 				return 1;
769 			return 0;
770 		}
771 		if(copyau(&p->to, v))
772 			return 1;
773 		return 0;
774 
775 	case ARETURN:	/* funny */
776 		if(v->type == D_REG)
777 			if(v->reg == REGRET)
778 				return 2;
779 		if(v->type == D_FREG)
780 			if(v->reg == FREGRET)
781 				return 2;
782 
783 	case ABL:	/* funny */
784 		if(v->type == D_REG) {
785 			if(v->reg <= REGEXT && v->reg > exregoffset)
786 				return 2;
787 			if(v->reg == REGARG)
788 				return 2;
789 		}
790 		if(v->type == D_FREG) {
791 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
792 				return 2;
793 		}
794 
795 		if(s != A) {
796 			if(copysub(&p->to, v, s, 1))
797 				return 1;
798 			return 0;
799 		}
800 		if(copyau(&p->to, v))
801 			return 4;
802 		return 3;
803 
804 	case ATEXT:	/* funny */
805 		if(v->type == D_REG)
806 			if(v->reg == REGARG)
807 				return 3;
808 		return 0;
809 	}
810 	return 0;
811 }
812 
813 int
814 a2type(Prog *p)
815 {
816 
817 	switch(p->as) {
818 	case AADD:
819 	case AADDC:
820 	case AADDCC:
821 	case AADDCCC:
822 	case AADDE:
823 	case AADDECC:
824 	case AADDME:
825 	case AADDMECC:
826 	case AADDZE:
827 	case AADDZECC:
828 	case ASUB:
829 	case ASUBC:
830 	case ASUBCC:
831 	case ASUBCCC:
832 	case ASUBE:
833 	case ASUBECC:
834 	case ASUBME:
835 	case ASUBMECC:
836 	case ASUBZE:
837 	case ASUBZECC:
838 	case ASLW:
839 	case ASLWCC:
840 	case ASRW:
841 	case ASRWCC:
842 	case ASRAW:
843 	case ASRAWCC:
844 	case AOR:
845 	case AORCC:
846 	case AORN:
847 	case AORNCC:
848 	case AAND:
849 	case AANDCC:
850 	case AANDN:
851 	case AANDNCC:
852 	case AXOR:
853 	case AXORCC:
854 	case ANEG:
855 	case ANEGCC:
856 	case AMULHW:
857 	case AMULHWU:
858 	case AMULLW:
859 	case AMULLWCC:
860 	case ADIVW:
861 	case ADIVWCC:
862 	case ADIVWU:
863 	case ADIVWUCC:
864 	case AREM:
865 	case AREMCC:
866 	case AREMU:
867 	case AREMUCC:
868 	case ANAND:
869 	case ANANDCC:
870 	case ANOR:
871 	case ANORCC:
872 	case ARLWMI:
873 	case ARLWMICC:
874 	case ARLWNM:
875 	case ARLWNMCC:
876 		return D_REG;
877 
878 	case AFADDS:
879 	case AFADDSCC:
880 	case AFADD:
881 	case AFADDCC:
882 	case AFSUBS:
883 	case AFSUBSCC:
884 	case AFSUB:
885 	case AFSUBCC:
886 	case AFMULS:
887 	case AFMULSCC:
888 	case AFMUL:
889 	case AFMULCC:
890 	case AFDIVS:
891 	case AFDIVSCC:
892 	case AFDIV:
893 	case AFDIVCC:
894 	case AFNEG:
895 	case AFNEGCC:
896 		return D_FREG;
897 	}
898 	return D_NONE;
899 }
900 
901 /*
902  * direct reference,
903  * could be set/use depending on
904  * semantics
905  */
906 int
907 copyas(Adr *a, Adr *v)
908 {
909 
910 	if(regtyp(v))
911 		if(a->type == v->type)
912 		if(a->reg == v->reg)
913 			return 1;
914 	return 0;
915 }
916 
917 /*
918  * either direct or indirect
919  */
920 int
921 copyau(Adr *a, Adr *v)
922 {
923 
924 	if(copyas(a, v))
925 		return 1;
926 	if(v->type == D_REG)
927 		if(a->type == D_OREG)
928 			if(v->reg == a->reg)
929 				return 1;
930 	return 0;
931 }
932 
933 int
934 copyau1(Prog *p, Adr *v)
935 {
936 
937 	if(regtyp(v))
938 		if(p->from.type == v->type || p->to.type == v->type)
939 		if(p->reg == v->reg) {
940 			if(a2type(p) != v->type)
941 				print("botch a2type %P\n", p);
942 			return 1;
943 		}
944 	return 0;
945 }
946 
947 /*
948  * substitute s for v in a
949  * return failure to substitute
950  */
951 int
952 copysub(Adr *a, Adr *v, Adr *s, int f)
953 {
954 
955 	if(f)
956 	if(copyau(a, v))
957 		a->reg = s->reg;
958 	return 0;
959 }
960 
961 int
962 copysub1(Prog *p1, Adr *v, Adr *s, int f)
963 {
964 
965 	if(f)
966 	if(copyau1(p1, v))
967 		p1->reg = s->reg;
968 	return 0;
969 }
970