xref: /inferno-os/utils/qc/peep.c (revision e57c7e16a3789cd4de1a3c2560d49b1ee39cd10a)
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 		case ARLWMI:
429 		case ARLWMICC:
430 
431 		case AFADD:
432 		case AFADDS:
433 		case AFSUB:
434 		case AFSUBS:
435 		case AFMUL:
436 		case AFMULS:
437 		case AFDIV:
438 		case AFDIVS:
439 			if(p->to.type == v1->type)
440 			if(p->to.reg == v1->reg) {
441 				if(p->reg == NREG)
442 					p->reg = p->to.reg;
443 				goto gotit;
444 			}
445 			break;
446 
447 		case AADDME:
448 		case AADDMECC:
449 		case AADDZE:
450 		case AADDZECC:
451 		case ASUBME:
452 		case ASUBMECC:
453 		case ASUBZE:
454 		case ASUBZECC:
455 		case ANEG:
456 		case ANEGCC:
457 		case AFNEG:
458 		case AFNEGCC:
459 		case AFMOVS:
460 		case AFMOVD:
461 		case AMOVW:
462 			if(p->to.type == v1->type)
463 			if(p->to.reg == v1->reg)
464 				goto gotit;
465 			break;
466 		}
467 		if(copyau(&p->from, v2) ||
468 		   copyau1(p, v2) ||
469 		   copyau(&p->to, v2))
470 			break;
471 		if(copysub(&p->from, v1, v2, 0) ||
472 		   copysub1(p, v1, v2, 0) ||
473 		   copysub(&p->to, v1, v2, 0))
474 			break;
475 	}
476 	return 0;
477 
478 gotit:
479 	copysub(&p->to, v1, v2, 1);
480 	if(debug['P']) {
481 		print("gotit: %D->%D\n%P", v1, v2, r->prog);
482 		if(p->from.type == v2->type)
483 			print(" excise");
484 		print("\n");
485 	}
486 	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
487 		p = r->prog;
488 		copysub(&p->from, v1, v2, 1);
489 		copysub1(p, v1, v2, 1);
490 		copysub(&p->to, v1, v2, 1);
491 		if(debug['P'])
492 			print("%P\n", r->prog);
493 	}
494 	t = v1->reg;
495 	v1->reg = v2->reg;
496 	v2->reg = t;
497 	if(debug['P'])
498 		print("%P last\n", r->prog);
499 	return 1;
500 }
501 
502 /*
503  * The idea is to remove redundant copies.
504  *	v1->v2	F=0
505  *	(use v2	s/v2/v1/)*
506  *	set v1	F=1
507  *	use v2	return fail
508  *	-----------------
509  *	v1->v2	F=0
510  *	(use v2	s/v2/v1/)*
511  *	set v1	F=1
512  *	set v2	return success
513  */
514 int
515 copyprop(Reg *r0)
516 {
517 	Prog *p;
518 	Adr *v1, *v2;
519 	Reg *r;
520 
521 	p = r0->prog;
522 	v1 = &p->from;
523 	v2 = &p->to;
524 	if(copyas(v1, v2))
525 		return 1;
526 	for(r=firstr; r!=R; r=r->link)
527 		r->active = 0;
528 	return copy1(v1, v2, r0->s1, 0);
529 }
530 
531 int
532 copy1(Adr *v1, Adr *v2, Reg *r, int f)
533 {
534 	int t;
535 	Prog *p;
536 
537 	if(r->active) {
538 		if(debug['P'])
539 			print("act set; return 1\n");
540 		return 1;
541 	}
542 	r->active = 1;
543 	if(debug['P'])
544 		print("copy %D->%D f=%d\n", v1, v2, f);
545 	for(; r != R; r = r->s1) {
546 		p = r->prog;
547 		if(debug['P'])
548 			print("%P", p);
549 		if(!f && uniqp(r) == R) {
550 			f = 1;
551 			if(debug['P'])
552 				print("; merge; f=%d", f);
553 		}
554 		t = copyu(p, v2, A);
555 		switch(t) {
556 		case 2:	/* rar, cant split */
557 			if(debug['P'])
558 				print("; %Drar; return 0\n", v2);
559 			return 0;
560 
561 		case 3:	/* set */
562 			if(debug['P'])
563 				print("; %Dset; return 1\n", v2);
564 			return 1;
565 
566 		case 1:	/* used, substitute */
567 		case 4:	/* use and set */
568 			if(f) {
569 				if(!debug['P'])
570 					return 0;
571 				if(t == 4)
572 					print("; %Dused+set and f=%d; return 0\n", v2, f);
573 				else
574 					print("; %Dused and f=%d; return 0\n", v2, f);
575 				return 0;
576 			}
577 			if(copyu(p, v2, v1)) {
578 				if(debug['P'])
579 					print("; sub fail; return 0\n");
580 				return 0;
581 			}
582 			if(debug['P'])
583 				print("; sub%D/%D", v2, v1);
584 			if(t == 4) {
585 				if(debug['P'])
586 					print("; %Dused+set; return 1\n", v2);
587 				return 1;
588 			}
589 			break;
590 		}
591 		if(!f) {
592 			t = copyu(p, v1, A);
593 			if(!f && (t == 2 || t == 3 || t == 4)) {
594 				f = 1;
595 				if(debug['P'])
596 					print("; %Dset and !f; f=%d", v1, f);
597 			}
598 		}
599 		if(debug['P'])
600 			print("\n");
601 		if(r->s2)
602 			if(!copy1(v1, v2, r->s2, f))
603 				return 0;
604 	}
605 	return 1;
606 }
607 
608 /*
609  * return
610  * 1 if v only used (and substitute),
611  * 2 if read-alter-rewrite
612  * 3 if set
613  * 4 if set and used
614  * 0 otherwise (not touched)
615  */
616 int
617 copyu(Prog *p, Adr *v, Adr *s)
618 {
619 
620 	switch(p->as) {
621 
622 	default:
623 		if(debug['P'])
624 			print(" (?)");
625 		return 2;
626 
627 
628 	case ANOP:	/* read, write */
629 	case AMOVW:
630 	case AMOVH:
631 	case AMOVHZ:
632 	case AMOVB:
633 	case AMOVBZ:
634 
635 	case ANEG:
636 	case ANEGCC:
637 	case AADDME:
638 	case AADDMECC:
639 	case AADDZE:
640 	case AADDZECC:
641 	case ASUBME:
642 	case ASUBMECC:
643 	case ASUBZE:
644 	case ASUBZECC:
645 
646 	case AFCTIW:
647 	case AFCTIWZ:
648 	case AFMOVS:
649 	case AFMOVD:
650 	case AFRSP:
651 	case AFNEG:
652 	case AFNEGCC:
653 		if(s != A) {
654 			if(copysub(&p->from, v, s, 1))
655 				return 1;
656 			if(!copyas(&p->to, v))
657 				if(copysub(&p->to, v, s, 1))
658 					return 1;
659 			return 0;
660 		}
661 		if(copyas(&p->to, v)) {
662 			if(copyau(&p->from, v))
663 				return 4;
664 			return 3;
665 		}
666 		if(copyau(&p->from, v))
667 			return 1;
668 		if(copyau(&p->to, v))
669 			return 1;
670 		return 0;
671 
672 	case AADD:	/* read read write */
673 	case AADDC:
674 	case AADDE:
675 	case ASUB:
676 	case ASLW:
677 	case ASRW:
678 	case ASRAW:
679 	case AOR:
680 	case AORCC:
681 	case AORN:
682 	case AORNCC:
683 	case AAND:
684 	case AANDCC:
685 	case AANDN:
686 	case AANDNCC:
687 	case ANAND:
688 	case ANANDCC:
689 	case ANOR:
690 	case ANORCC:
691 	case AXOR:
692 	case AMULHW:
693 	case AMULHWU:
694 	case AMULLW:
695 	case ADIVW:
696 	case ADIVWU:
697 	case AREM:
698 	case AREMU:
699 	case ARLWMI:
700 	case ARLWMICC:
701 	case ARLWNM:
702 	case ARLWNMCC:
703 
704 	case AFADDS:
705 	case AFADD:
706 	case AFSUBS:
707 	case AFSUB:
708 	case AFMULS:
709 	case AFMUL:
710 	case AFDIVS:
711 	case AFDIV:
712 		if(s != A) {
713 			if(copysub(&p->from, v, s, 1))
714 				return 1;
715 			if(copysub1(p, v, s, 1))
716 				return 1;
717 			if(!copyas(&p->to, v))
718 				if(copysub(&p->to, v, s, 1))
719 					return 1;
720 			return 0;
721 		}
722 		if(copyas(&p->to, v)) {
723 			if(p->reg == NREG)
724 				p->reg = p->to.reg;
725 			if(copyau(&p->from, v))
726 				return 4;
727 			if(copyau1(p, v))
728 				return 4;
729 			return 3;
730 		}
731 		if(copyau(&p->from, v))
732 			return 1;
733 		if(copyau1(p, v))
734 			return 1;
735 		if(copyau(&p->to, v))
736 			return 1;
737 		return 0;
738 
739 	case ABEQ:
740 	case ABGT:
741 	case ABGE:
742 	case ABLT:
743 	case ABLE:
744 	case ABNE:
745 	case ABVC:
746 	case ABVS:
747 		break;
748 
749 	case ACMP:	/* read read */
750 	case ACMPU:
751 	case AFCMPO:
752 	case AFCMPU:
753 		if(s != A) {
754 			if(copysub(&p->from, v, s, 1))
755 				return 1;
756 			return copysub(&p->to, v, s, 1);
757 		}
758 		if(copyau(&p->from, v))
759 			return 1;
760 		if(copyau(&p->to, v))
761 			return 1;
762 		break;
763 
764 	case ABR:	/* funny */
765 		if(s != A) {
766 			if(copysub(&p->to, v, s, 1))
767 				return 1;
768 			return 0;
769 		}
770 		if(copyau(&p->to, v))
771 			return 1;
772 		return 0;
773 
774 	case ARETURN:	/* funny */
775 		if(v->type == D_REG)
776 			if(v->reg == REGRET)
777 				return 2;
778 		if(v->type == D_FREG)
779 			if(v->reg == FREGRET)
780 				return 2;
781 
782 	case ABL:	/* funny */
783 		if(v->type == D_REG) {
784 			if(v->reg <= REGEXT && v->reg > exregoffset)
785 				return 2;
786 			if(v->reg == REGARG)
787 				return 2;
788 		}
789 		if(v->type == D_FREG) {
790 			if(v->reg <= FREGEXT && v->reg > exfregoffset)
791 				return 2;
792 		}
793 
794 		if(s != A) {
795 			if(copysub(&p->to, v, s, 1))
796 				return 1;
797 			return 0;
798 		}
799 		if(copyau(&p->to, v))
800 			return 4;
801 		return 3;
802 
803 	case ATEXT:	/* funny */
804 		if(v->type == D_REG)
805 			if(v->reg == REGARG)
806 				return 3;
807 		return 0;
808 	}
809 	return 0;
810 }
811 
812 int
813 a2type(Prog *p)
814 {
815 
816 	switch(p->as) {
817 	case AADD:
818 	case AADDC:
819 	case AADDCC:
820 	case AADDCCC:
821 	case AADDE:
822 	case AADDECC:
823 	case AADDME:
824 	case AADDMECC:
825 	case AADDZE:
826 	case AADDZECC:
827 	case ASUB:
828 	case ASUBC:
829 	case ASUBCC:
830 	case ASUBCCC:
831 	case ASUBE:
832 	case ASUBECC:
833 	case ASUBME:
834 	case ASUBMECC:
835 	case ASUBZE:
836 	case ASUBZECC:
837 	case ASLW:
838 	case ASLWCC:
839 	case ASRW:
840 	case ASRWCC:
841 	case ASRAW:
842 	case ASRAWCC:
843 	case AOR:
844 	case AORCC:
845 	case AORN:
846 	case AORNCC:
847 	case AAND:
848 	case AANDCC:
849 	case AANDN:
850 	case AANDNCC:
851 	case AXOR:
852 	case AXORCC:
853 	case ANEG:
854 	case ANEGCC:
855 	case AMULHW:
856 	case AMULHWU:
857 	case AMULLW:
858 	case AMULLWCC:
859 	case ADIVW:
860 	case ADIVWCC:
861 	case ADIVWU:
862 	case ADIVWUCC:
863 	case AREM:
864 	case AREMCC:
865 	case AREMU:
866 	case AREMUCC:
867 	case ANAND:
868 	case ANANDCC:
869 	case ANOR:
870 	case ANORCC:
871 	case ARLWMI:
872 	case ARLWMICC:
873 	case ARLWNM:
874 	case ARLWNMCC:
875 		return D_REG;
876 
877 	case AFADDS:
878 	case AFADDSCC:
879 	case AFADD:
880 	case AFADDCC:
881 	case AFSUBS:
882 	case AFSUBSCC:
883 	case AFSUB:
884 	case AFSUBCC:
885 	case AFMULS:
886 	case AFMULSCC:
887 	case AFMUL:
888 	case AFMULCC:
889 	case AFDIVS:
890 	case AFDIVSCC:
891 	case AFDIV:
892 	case AFDIVCC:
893 	case AFNEG:
894 	case AFNEGCC:
895 		return D_FREG;
896 	}
897 	return D_NONE;
898 }
899 
900 /*
901  * direct reference,
902  * could be set/use depending on
903  * semantics
904  */
905 int
906 copyas(Adr *a, Adr *v)
907 {
908 
909 	if(regtyp(v))
910 		if(a->type == v->type)
911 		if(a->reg == v->reg)
912 			return 1;
913 	return 0;
914 }
915 
916 /*
917  * either direct or indirect
918  */
919 int
920 copyau(Adr *a, Adr *v)
921 {
922 
923 	if(copyas(a, v))
924 		return 1;
925 	if(v->type == D_REG)
926 		if(a->type == D_OREG)
927 			if(v->reg == a->reg)
928 				return 1;
929 	return 0;
930 }
931 
932 int
933 copyau1(Prog *p, Adr *v)
934 {
935 
936 	if(regtyp(v))
937 		if(p->from.type == v->type || p->to.type == v->type)
938 		if(p->reg == v->reg) {
939 			if(a2type(p) != v->type)
940 				print("botch a2type %P\n", p);
941 			return 1;
942 		}
943 	return 0;
944 }
945 
946 /*
947  * substitute s for v in a
948  * return failure to substitute
949  */
950 int
951 copysub(Adr *a, Adr *v, Adr *s, int f)
952 {
953 
954 	if(f)
955 	if(copyau(a, v))
956 		a->reg = s->reg;
957 	return 0;
958 }
959 
960 int
961 copysub1(Prog *p1, Adr *v, Adr *s, int f)
962 {
963 
964 	if(f)
965 	if(copyau1(p1, v))
966 		p1->reg = s->reg;
967 	return 0;
968 }
969