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