xref: /netbsd/external/bsd/pcc/dist/pcc/arch/vax/order.c (revision 6935091c)
1 /*	Id: order.c,v 1.10 2014/10/12 13:16:32 ragge Exp 	*/
2 /*	$NetBSD: order.c,v 1.1.1.4 2016/02/09 20:28:36 plunky Exp $	*/
3 /*
4  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * Redistributions of source code and documentation must retain the above
11  * copyright notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditionsand the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * All advertising materials mentioning features or use of this software
16  * must display the following acknowledgement:
17  * 	This product includes software developed or owned by Caldera
18  *	International, Inc.
19  * Neither the name of Caldera International, Inc. nor the names of other
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 # include "pass2.h"
38 
39 int canaddr(NODE *);
40 
41 int maxargs = { -1 };
42 
43 #if 0
44 stoasg( p, o ) register NODE *p; {
45 	/* should the assignment op p be stored,
46 	   given that it lies as the right operand of o
47 	   (or the left, if o==UNARY MUL) */
48 /*
49 	if( p->op == INCR || p->op == DECR ) return;
50 	if( o==UNARY MUL && p->left->op == REG && !isbreg(p->left->rval) ) SETSTO(p,INAREG);
51  */
52 	}
53 
54 int
55 deltest( p ) register NODE *p; {
56 	/* should we delay the INCR or DECR operation p */
57 	p = p->n_left;
58 	return( p->n_op == REG || p->n_op == NAME || p->n_op == OREG );
59 	}
60 
61 autoincr( p ) NODE *p; {
62 	register NODE *q = p->left, *r;
63 
64 	if( q->op == INCR && (r=q->left)->op == REG &&
65 	    ISPTR(q->type) && p->type == DECREF(q->type) &&
66 	    tlen(p) == q->right->lval ) return(1);
67 
68 	return(0);
69 	}
70 
71 mkadrs(p) register NODE *p; {
72 	register o;
73 
74 	o = p->op;
75 
76 	if( asgop(o) ){
77 		if( p->left->su >= p->right->su ){
78 			if( p->left->op == UNARY MUL ){
79 				SETSTO( p->left->left, INTEMP );
80 				}
81 			else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
82 				SETSTO( p->left->left->left, INTEMP );
83 				}
84 			else { /* should be only structure assignment */
85 				SETSTO( p->left, INTEMP );
86 				}
87 			}
88 		else SETSTO( p->right, INTEMP );
89 		}
90 	else {
91 		if( p->left->su > p->right->su ){
92 			SETSTO( p->left, INTEMP );
93 			}
94 		else {
95 			SETSTO( p->right, INTEMP );
96 			}
97 		}
98 	}
99 #endif
100 
101 int
notoff(TWORD t,int r,CONSZ off,char * cp)102 notoff(TWORD t, int r, CONSZ off, char *cp)
103 {
104 	/* is it legal to make an OREG or NAME entry which has an
105 	 * offset of off, (from a register of r), if the
106 	 * resulting thing had type t */
107 
108 /*	if( r == R0 ) return( 1 );  / * NO */
109 	return(0);  /* YES */
110 	}
111 
112 # define max(x,y) ((x)<(y)?(y):(x))
113 
114 #if 0
115 sucomp( p ) register NODE *p; {
116 
117 	/* set the su field in the node to the sethi-ullman
118 	   number, or local equivalent */
119 
120 	register o, ty, sul, sur, r;
121 
122 	o = p->op;
123 	ty = optype( o );
124 	p->su = szty( p->type );   /* 2 for float or double, else 1 */;
125 
126 	if( ty == LTYPE ){
127 		if( o == OREG ){
128 			r = p->rval;
129 			/* oreg cost is (worst case) 1 + number of temp registers used */
130 			if( R2TEST(r) ){
131 				if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->su;
132 				if( istreg(R2UPK2(r)) ) ++p->su;
133 				}
134 			else {
135 				if( istreg( r ) ) ++p->su;
136 				}
137 			}
138 		if( p->su == szty(p->type) &&
139 		   (p->op!=REG || !istreg(p->rval)) &&
140 		   (p->type==INT || p->type==UNSIGNED || p->type==DOUBLE) )
141 			p->su = 0;
142 		return;
143 		}
144 
145 	else if( ty == UTYPE ){
146 		switch( o ) {
147 		case UNARY CALL:
148 		case UNARY STCALL:
149 			p->su = fregs;  /* all regs needed */
150 			return;
151 
152 		default:
153 			p->su =  p->left->su + (szty( p->type ) > 1 ? 2 : 0) ;
154 			return;
155 			}
156 		}
157 
158 
159 	/* If rhs needs n, lhs needs m, regular su computation */
160 
161 	sul = p->left->su;
162 	sur = p->right->su;
163 
164 	if( o == ASSIGN ){
165 		/* computed by doing right, then left (if not in mem), then doing it */
166 		p->su = max(sur,sul+1);
167 		return;
168 		}
169 
170 	if( o == CALL || o == STCALL ){
171 		/* in effect, takes all free registers */
172 		p->su = fregs;
173 		return;
174 		}
175 
176 	if( o == STASG ){
177 		/* right, then left */
178 		p->su = max( max( 1+sul, sur), fregs );
179 		return;
180 		}
181 
182 	if( asgop(o) ){
183 		/* computed by doing right, doing left address, doing left, op, and store */
184 		p->su = max(sur,sul+2);
185 /*
186 		if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->su = max(p->su,fregs);
187  */
188 		return;
189 		}
190 
191 	switch( o ){
192 	case ANDAND:
193 	case OROR:
194 	case QUEST:
195 	case COLON:
196 	case COMOP:
197 		p->su = max( max(sul,sur), 1);
198 		return;
199 
200 	case PLUS:
201 	case OR:
202 	case ER:
203 		/* commutative ops; put harder on left */
204 		if( p->right->su > p->left->su && !istnode(p->left) ){
205 			register NODE *temp;
206 			temp = p->left;
207 			p->left = p->right;
208 			p->right = temp;
209 			}
210 		break;
211 		}
212 
213 	/* binary op, computed by left, then right, then do op */
214 	p->su = max(sul,szty(p->right->type)+sur);
215 /*
216 	if( o==MUL||o==DIV||o==MOD) p->su = max(p->su,fregs);
217  */
218 
219 	}
220 
221 int radebug = 0;
222 
223 rallo( p, down ) NODE *p; {
224 	/* do register allocation */
225 	register o, type, down1, down2, ty;
226 
227 	if( radebug ) printf( "rallo( %o, %d )\n", p, down );
228 
229 	down2 = NOPREF;
230 	p->rall = down;
231 	down1 = ( down &= ~MUSTDO );
232 
233 	ty = optype( o = p->op );
234 	type = p->type;
235 
236 
237 	if( type == DOUBLE || type == FLOAT ){
238 		if( o == FORCE ) down1 = R0|MUSTDO;
239 		}
240 	else switch( o ) {
241 	case ASSIGN:
242 		down1 = NOPREF;
243 		down2 = down;
244 		break;
245 
246 /*
247 	case MUL:
248 	case DIV:
249 	case MOD:
250 		down1 = R3|MUSTDO;
251 		down2 = R5|MUSTDO;
252 		break;
253 
254 	case ASG MUL:
255 	case ASG DIV:
256 	case ASG MOD:
257 		p->left->rall = down1 = R3|MUSTDO;
258 		if( p->left->op == UNARY MUL ){
259 			rallo( p->left->left, R4|MUSTDO );
260 			}
261 		else if( p->left->op == FLD  && p->left->left->op == UNARY MUL ){
262 			rallo( p->left->left->left, R4|MUSTDO );
263 			}
264 		else rallo( p->left, R3|MUSTDO );
265 		rallo( p->right, R5|MUSTDO );
266 		return;
267  */
268 
269 	case CALL:
270 	case STASG:
271 	case EQ:
272 	case NE:
273 	case GT:
274 	case GE:
275 	case LT:
276 	case LE:
277 	case NOT:
278 	case ANDAND:
279 	case OROR:
280 		down1 = NOPREF;
281 		break;
282 
283 	case FORCE:
284 		down1 = R0|MUSTDO;
285 		break;
286 
287 		}
288 
289 	if( ty != LTYPE ) rallo( p->left, down1 );
290 	if( ty == BITYPE ) rallo( p->right, down2 );
291 
292 	}
293 #endif
294 
295 /*
296  * Turn a UMUL-referenced node into OREG.
297  * Be careful about register classes, this is a place where classes change.
298  */
299 void
offstar(NODE * p,int shape)300 offstar(NODE *p, int shape)
301 {
302 
303 	if (x2debug)
304 		printf("offstar(%p)\n", p);
305 
306 	if (isreg(p))
307 		return; /* Is already OREG */
308 
309 #if 0 /* notyet */
310 	NODE *r;
311 	r = p->n_right;
312 	if( p->n_op == PLUS || p->n_op == MINUS ){
313 		if( r->n_op == ICON ){
314 			if (isreg(p->n_left) == 0)
315 				(void)geninsn(p->n_left, INAREG);
316 			/* Converted in ormake() */
317 			return;
318 		}
319 		if (r->n_op == LS && r->n_right->n_op == ICON &&
320 		    r->n_right->n_lval == 2 && p->n_op == PLUS) {
321 			if (isreg(p->n_left) == 0)
322 				(void)geninsn(p->n_left, INAREG);
323 			if (isreg(r->n_left) == 0)
324 				(void)geninsn(r->n_left, INAREG);
325 			return;
326 		}
327 	}
328 #endif
329 	(void)geninsn(p, INAREG);
330 }
331 
332 
333 #if 0
334 void
335 offstar( p, s ) register NODE *p; {
336 	if( p->n_op == PLUS ) {
337 		if( p->n_left->n_su == fregs ) {
338 			order( p->n_left, INAREG );
339 			return;
340 		} else if( p->n_right->n_su == fregs ) {
341 			order( p->n_right, INAREG );
342 			return;
343 		}
344 		if( p->n_left->n_op==LS &&
345 		  (p->n_left->n_left->n_op!=REG || tlen(p->n_left->n_left)!=sizeof(int) ) ) {
346 			order( p->n_left->n_left, INAREG );
347 			return;
348 		}
349 		if( p->n_right->n_op==LS &&
350 		  (p->n_right->n_left->n_op!=REG || tlen(p->n_right->n_left)!=sizeof(int) ) ) {
351 			order( p->n_right->n_left, INAREG );
352 			return;
353 		}
354 		if( p->n_type == (PTR|CHAR) || p->n_type == (PTR|UCHAR) ) {
355 			if( p->n_left->n_op!=REG || tlen(p->n_left)!=sizeof(int) ) {
356 				order( p->n_left, INAREG );
357 				return;
358 			}
359 			else if( p->n_right->n_op!=REG || tlen(p->n_right)!=sizeof(int) ) {
360 				order(p->n_right, INAREG);
361 				return;
362 			}
363 		}
364 	}
365 	if( p->n_op == PLUS || p->n_op == MINUS ){
366 		if( p->n_right->n_op == ICON ){
367 			p = p->n_left;
368 			order( p , INAREG);
369 			return;
370 			}
371 		}
372 
373 	if( p->n_op == UMUL && !canaddr(p) ) {
374 		offstar( p->n_left, 0 );
375 		return;
376 	}
377 
378 	order( p, INAREG );
379 	}
380 #endif
381 
382 int
setbin(p)383 setbin( p ) register NODE *p; {
384 
385 #if 0
386 	register int ro, rt;
387 
388 	rt = p->n_right->n_type;
389 	ro = p->n_right->n_op;
390 
391 	if( canaddr( p->n_left ) && !canaddr( p->n_right ) ) { /* address rhs */
392 		if( ro == UMUL ) {
393 			offstar( p->n_right->n_left, 0 );
394 			return(1);
395 		} else {
396 			order( p->n_right, INAREG|SOREG );
397 			return(1);
398 		}
399 	}
400 	if( !istnode( p->n_left) ) { /* try putting LHS into a reg */
401 /*		order( p->n_left, logop(p->n_op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/
402 		order( p->n_left, INAREG|INTAREG|INBREG|INTBREG|SOREG );
403 		return(1);
404 		}
405 	else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){
406 		offstar( p->n_right->n_left );
407 		return(1);
408 		}
409 	else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG &&
410 			ro != NAME && ro != OREG && ro != ICON ) ){
411 		order( p->n_right, INAREG|INBREG );
412 		return(1);
413 		}
414 /*
415 	else if( logop(p->n_op) && rt==USHORT ){  / * must get rhs into register */
416 /*
417 		order( p->n_right, INAREG );
418 		return( 1 );
419 		}
420  */
421 #endif
422 	return(0);
423 	}
424 
425 #if 0
426 int
427 setstr( p ) register NODE *p; { /* structure assignment */
428 	if( p->right->op != REG ){
429 		order( p->right, INTAREG );
430 		return(1);
431 		}
432 	p = p->left;
433 	if( p->op != NAME && p->op != OREG ){
434 		if( p->op != UNARY MUL ) cerror( "bad setstr" );
435 		order( p->left, INTAREG );
436 		return( 1 );
437 		}
438 	return( 0 );
439 	}
440 #endif
441 
442 int
setasg(p,s)443 setasg( p, s ) register NODE *p; {
444 
445 #if 0
446 	/* setup for assignment operator */
447 
448 	if( !canaddr(p->n_right) ) {
449 		if( p->n_right->n_op == UNARY MUL )
450 			offstar(p->n_right->n_left);
451 		else
452 			order( p->n_right, INAREG|INBREG|SOREG );
453 		return(1);
454 		}
455 	if( p->n_left->n_op == UMUL ) {
456 		offstar( p->n_left->n_left );
457 		return(1);
458 		}
459 	if( p->left->op == FLD && p->left->left->op == UNARY MUL ){
460 		offstar( p->left->left->left );
461 		return(1);
462 		}
463 /* FLD patch */
464 	if( p->left->op == FLD && !(p->right->type==INT || p->right->type==UNSIGNED)) {
465 		order( p->right, INAREG);
466 		return(1);
467 		}
468 /* end of FLD patch */
469 #endif
470 	return(0);
471 	}
472 
473 /* setup for unary operator */
474 int
setuni(NODE * p,int cookie)475 setuni(NODE *p, int cookie)
476 {
477 	return 0;
478 }
479 
480 
481 #if 0
482 int
483 setasop( p ) register NODE *p; {
484 	/* setup for =ops */
485 	register rt, ro;
486 
487 	rt = p->right->type;
488 	ro = p->right->op;
489 
490 	if( ro == UNARY MUL && rt != CHAR ){
491 		offstar( p->right->left );
492 		return(1);
493 		}
494 	if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT ||
495 			( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){
496 		order( p->right, INAREG|INBREG );
497 		return(1);
498 		}
499 /*
500 	if( (p->op == ASG LS || p->op == ASG RS) && ro != ICON && ro != REG ){
501 		order( p->right, INAREG );
502 		return(1);
503 		}
504  */
505 
506 
507 	p = p->left;
508 	if( p->op == FLD ) p = p->left;
509 
510 	switch( p->op ){
511 
512 	case REG:
513 	case ICON:
514 	case NAME:
515 	case OREG:
516 		return(0);
517 
518 	case UNARY MUL:
519 		if( p->left->op==OREG )
520 			return(0);
521 		else
522 			offstar( p->left );
523 		return(1);
524 
525 		}
526 	cerror( "illegal setasop" );
527 	}
528 #endif
529 
530 void
deflab(int l)531 deflab(int l)
532 {
533 	printf(LABFMT ":\n", l);
534 }
535 
536 #if 0
537 genargs( p, ptemp ) register NODE *p, *ptemp; {
538 	register NODE *pasg;
539 	register align;
540 	register size;
541 	register TWORD type;
542 
543 	/* generate code for the arguments */
544 
545 	/*  first, do the arguments on the right */
546 	while( p->op == CM ){
547 		genargs( p->right, ptemp );
548 		p->op = FREE;
549 		p = p->left;
550 		}
551 
552 	if( p->op == STARG ){ /* structure valued argument */
553 
554 		size = p->stsize;
555 		align = p->stalign;
556 
557  /*		ptemp->lval = (ptemp->lval/align)*align;  / * SETOFF for negative numbers */
558  		ptemp->lval = 0;	/* all moves to (sp) */
559 
560 		p->op = STASG;
561 		p->right = p->left;
562 		p->left = tcopy( ptemp );
563 
564 		/* the following line is done only with the knowledge
565 		that it will be undone by the STASG node, with the
566 		offset (lval) field retained */
567 
568 		if( p->right->op == OREG ) p->right->op = REG;  /* only for temporaries */
569 
570  		order( p, FORARG );
571 		ptemp->lval += size;
572 		return;
573 		}
574 
575 	/* ordinary case */
576 
577 	order( p, FORARG );
578 	}
579 
580 argsize( p ) register NODE *p; {
581 	register t;
582 	t = 0;
583 	if( p->op == CM ){
584 		t = argsize( p->left );
585 		p = p->right;
586 		}
587 	if( p->type == DOUBLE || p->type == FLOAT ){
588 		SETOFF( t, 4 );
589 		return( t+8 );
590 		}
591 	else if( p->op == STARG ){
592  		SETOFF( t, 4 );  /* alignment */
593  		return( t + ((p->stsize+3)/4)*4 );  /* size */
594 		}
595 	else {
596 		SETOFF( t, 4 );
597 		return( t+4 );
598 		}
599 	}
600 #endif
601 
602 /*
603  * Special handling of some instruction register allocation.
604  */
605 struct rspecial *
nspecial(struct optab * q)606 nspecial(struct optab *q)
607 {
608 	switch (q->op) {
609 	case STARG:
610 	case STASG:
611 		{
612 		static struct rspecial s[] = {
613 		    { NEVER, R0, }, { NEVER, R1, }, { NEVER, R2, },
614 		    { NEVER, R3, }, { NEVER, R4, }, { NEVER, R5 }, { 0 } };
615 		return s;
616 		}
617 	case MOD:
618 	case MUL:
619 	case DIV:
620 		{
621 		static struct rspecial s[] = {
622 		    { NEVER, R0, }, { NEVER, R1, }, { NEVER, R2, },
623 		    { NEVER, R3, }, { NEVER, R4, }, { NEVER, R5 },
624 		    { NRES, XR0 }, { 0 }, };
625 		return s;
626 		}
627 	default:
628 		comperr("nspecial");
629 		return NULL;
630 	}
631 }
632 
633 /*
634  * Set evaluation order of a binary node if it differs from default.
635  */
636 int
setorder(NODE * p)637 setorder(NODE *p)
638 {
639 	return 0; /* nothing differs on vax */
640 }
641 
642 /*
643  * Do the actual conversion of offstar-found OREGs into real OREGs.
644  */
645 void
myormake(NODE * q)646 myormake(NODE *q)
647 {
648 }
649 /*
650  * Set registers "live" at function calls (like arguments in registers).
651  * This is for liveness analysis of registers.
652  */
653 int *
livecall(NODE * p)654 livecall(NODE *p)
655 {
656 	static int r[1] = { -1 }; /* Terminate with -1 */
657 
658 	return &r[0];
659 }
660 
661 /*
662  * Signal whether the instruction is acceptable for this target.
663  */
664 int
acceptable(struct optab * op)665 acceptable(struct optab *op)
666 {
667 	return 1;
668 }
669