upput calling sequence changes
[unix-history] / usr / src / old / pcc / mip / allo.c
CommitLineData
262eaf56 1#ifndef lint
57b6b508 2static char *sccsid ="@(#)allo.c 4.8 (Berkeley) %G%";
262eaf56
RC
3#endif lint
4
69023ebb 5# include "pass2.h"
e91423bb
RC
6
7NODE resc[3];
8
9int busy[REGSZ];
10
11int maxa, mina, maxb, minb;
12
13# ifndef ALLO0
14allo0(){ /* free everything */
15
16 register i;
17
18 maxa = maxb = -1;
19 mina = minb = 0;
20
21 REGLOOP(i){
22 busy[i] = 0;
23 if( rstatus[i] & STAREG ){
24 if( maxa<0 ) mina = i;
25 maxa = i;
26 }
27 if( rstatus[i] & STBREG ){
28 if( maxb<0 ) minb = i;
29 maxb = i;
30 }
31 }
32 }
33# endif
34
e91423bb
RC
35# ifndef ALLO
36allo( p, q ) NODE *p; struct optab *q; {
37
38 register n, i, j;
39 int either;
40
41 n = q->needs;
42 either = ( EITHER & n );
43 i = 0;
44
45 while( n & NACOUNT ){
46 resc[i].in.op = REG;
47 resc[i].tn.rval = freereg( p, n&NAMASK );
48 resc[i].tn.lval = 0;
49#ifdef FLEXNAMES
50 resc[i].in.name = "";
51#else
52 resc[i].in.name[0] = '\0';
53#endif
54 n -= NAREG;
55 ++i;
56 }
57
58 if (either) { /* all or nothing at all */
59 for( j = 0; j < i; j++ )
60 if( resc[j].tn.rval < 0 ) { /* nothing */
61 i = 0;
62 break;
63 }
64 if( i != 0 ) goto ok; /* all */
65 }
66
67 while( n & NBCOUNT ){
68 resc[i].in.op = REG;
69 resc[i].tn.rval = freereg( p, n&NBMASK );
70 resc[i].tn.lval = 0;
71#ifdef FLEXNAMES
72 resc[i].in.name = "";
73#else
74 resc[i].in.name[0] = '\0';
75#endif
76 n -= NBREG;
77 ++i;
78 }
79 if (either) { /* all or nothing at all */
80 for( j = 0; j < i; j++ )
81 if( resc[j].tn.rval < 0 ) { /* nothing */
82 i = 0;
83 break;
84 }
85 if( i != 0 ) goto ok; /* all */
86 }
87
88 if( n & NTMASK ){
89 resc[i].in.op = OREG;
90 resc[i].tn.rval = TMPREG;
91 if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){
92 resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT );
93 }
94 else {
95 resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP );
96 }
97#ifdef FLEXNAMES
98 resc[i].in.name = "";
99#else
100 resc[i].in.name[0] = '\0';
101#endif
102
103 resc[i].tn.lval = BITOOR(resc[i].tn.lval);
104 ++i;
105 }
106
107 /* turn off "temporarily busy" bit */
108
109 ok:
110 REGLOOP(j){
111 busy[j] &= ~TBUSY;
112 }
113
114 for( j=0; j<i; ++j ) if( resc[j].tn.rval < 0 ) return(0);
115 return(1);
116
117 }
118# endif
119
120extern unsigned int offsz;
121freetemp( k ){ /* allocate k integers worth of temp space */
122 /* we also make the convention that, if the number of words is more than 1,
123 /* it must be aligned for storing doubles... */
124
125# ifndef BACKTEMP
126 int t;
127
128 if( k>1 ){
129 SETOFF( tmpoff, ALDOUBLE );
130 }
131
132 t = tmpoff;
133 tmpoff += k*SZINT;
134 if( tmpoff > maxoff ) maxoff = tmpoff;
135 if( tmpoff >= offsz )
136 cerror( "stack overflow" );
137 if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
138 return(t);
139
140# else
141 tmpoff += k*SZINT;
142 if( k>1 ) {
143 SETOFF( tmpoff, ALDOUBLE );
144 }
145 if( tmpoff > maxoff ) maxoff = tmpoff;
146 if( tmpoff >= offsz )
147 cerror( "stack overflow" );
148 if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
149 return( -tmpoff );
150# endif
151 }
152
153freereg( p, n ) NODE *p; {
154 /* allocate a register of type n */
155 /* p gives the type, if floating */
156
157 register j;
158
159 /* not general; means that only one register (the result) OK for call */
160 if( callop(p->in.op) ){
161 j = callreg(p);
162 if( usable( p, n, j ) ) return( j );
163 /* have allocated callreg first */
164 }
165 j = p->in.rall & ~MUSTDO;
166 if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */
167 return( j );
168 }
169 if( n&NAMASK ){
170 for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){
171 if( usable(p,n,j) ){
172 return( j );
173 }
174 }
175 }
176 else if( n &NBMASK ){
177 for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){
178 if( usable(p,n,j) ){
179 return(j);
180 }
181 }
182 }
183
184 return( -1 );
185 }
186
187# ifndef USABLE
188usable( p, n, r ) NODE *p; {
189 /* decide if register r is usable in tree p to satisfy need n */
190
191 /* checks, for the moment */
192 if( !istreg(r) ) cerror( "usable asked about nontemp register" );
193
194 if( busy[r] > 1 ) return(0);
195 if( isbreg(r) ){
196 if( n&NAMASK ) return(0);
197 }
198 else {
199 if( n & NBMASK ) return(0);
200 }
a380d75d 201 /*
57b6b508
DS
202 * Some special cases that require register pairs...
203 * Have to check for ==, <=, etc. because the result is type int
204 * but need a register pair temp if either side is wide.
205 * For +=, *= etc. where lhs is narrow and rhs is wide, the temp
206 * register must be wide.
a380d75d 207 */
57b6b508
DS
208 if( (n&NAMASK) &&
209 (szty(p->in.type) == 2 ||
210 (logop(p->in.op) && (szty(p->in.left->in.type) == 2 ||
211 szty(p->in.right->in.type) == 2)) ||
212 (asgop(p->in.op) && szty(p->in.right->in.type) == 2 &&
213 szty(p->in.left->in.type) == 1))
214 ){
bd4e35d4 215#ifndef NOEVENODD
e91423bb 216 if( r&01 ) return(0);
bd4e35d4 217#endif
e91423bb
RC
218 if( !istreg(r+1) ) return( 0 );
219 if( busy[r+1] > 1 ) return( 0 );
220 if( busy[r] == 0 && busy[r+1] == 0 ||
221 busy[r+1] == 0 && shareit( p, r, n ) ||
222 busy[r] == 0 && shareit( p, r+1, n ) ){
223 busy[r] |= TBUSY;
224 busy[r+1] |= TBUSY;
225 return(1);
226 }
227 else return(0);
228 }
229 if( busy[r] == 0 ) {
230 busy[r] |= TBUSY;
231 return(1);
232 }
233
234 /* busy[r] is 1: is there chance for sharing */
235 return( shareit( p, r, n ) );
236
237 }
238# endif
239
240shareit( p, r, n ) NODE *p; {
241 /* can we make register r available by sharing from p
242 given that the need is n */
243 if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1);
244 if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1);
245 return(0);
246 }
247
248ushare( p, f, r ) NODE *p; {
249 /* can we find a register r to share on the left or right
250 (as f=='L' or 'R', respectively) of p */
251 p = getlr( p, f );
252 if( p->in.op == UNARY MUL ) p = p->in.left;
253 if( p->in.op == OREG ){
254 if( R2TEST(p->tn.rval) ){
255 return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) );
256 }
257 else return( r == p->tn.rval );
258 }
259 if( p->in.op == REG ){
260 return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) );
261 }
262 return(0);
263 }
264
265recl2( p ) register NODE *p; {
266 register r = p->tn.rval;
267#ifndef OLD
268 int op = p->in.op;
269 if (op == REG && r >= REGSZ)
270 op = OREG;
271 if( op == REG ) rfree( r, p->in.type );
272 else if( op == OREG ) {
273 if( R2TEST( r ) ) {
274 if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
275 rfree( R2UPK2( r ), INT );
276 }
277 else {
278 rfree( r, PTR+INT );
279 }
280 }
281#else
282 if( p->in.op == REG ) rfree( r, p->in.type );
283 else if( p->in.op == OREG ) {
284 if( R2TEST( r ) ) {
285 if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
286 rfree( R2UPK2( r ), INT );
287 }
288 else {
289 rfree( r, PTR+INT );
290 }
291 }
292#endif
293 }
294
295int rdebug = 0;
296
297# ifndef RFREE
298rfree( r, t ) TWORD t; {
299 /* mark register r free, if it is legal to do so */
300 /* t is the type */
301
302# ifndef BUG3
303 if( rdebug ){
304 printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
305 }
306# endif
307
308 if( istreg(r) ){
309 if( --busy[r] < 0 ) cerror( "register overfreed");
310 if( szty(t) == 2 ){
bd4e35d4
RC
311#ifdef NOEVENODD
312 if( istreg(r) ^ istreg(r+1) ) cerror( "illegal free" );
313#else
e91423bb 314 if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
bd4e35d4 315#endif
e91423bb
RC
316 if( --busy[r+1] < 0 ) cerror( "register overfreed" );
317 }
318 }
319 }
320# endif
321
322# ifndef RBUSY
323rbusy(r,t) TWORD t; {
324 /* mark register r busy */
325 /* t is the type */
326
327# ifndef BUG3
328 if( rdebug ){
329 printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
330 }
331# endif
332
333 if( istreg(r) ) ++busy[r];
334 if( szty(t) == 2 ){
335 if( istreg(r+1) ) ++busy[r+1];
bd4e35d4
RC
336#ifdef NOEVENODD
337 if( istreg(r) ^ istreg(r+1) ) cerror( "illegal register pair freed" );
338#else
e91423bb 339 if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
bd4e35d4 340#endif
e91423bb
RC
341 }
342 }
343# endif
344
345# ifndef BUG3
346rwprint( rw ){ /* print rewriting rule */
347 register i, flag;
348 static char * rwnames[] = {
349
350 "RLEFT",
351 "RRIGHT",
352 "RESC1",
353 "RESC2",
354 "RESC3",
355 0,
356 };
357
358 if( rw == RNULL ){
359 printf( "RNULL" );
360 return;
361 }
362
363 if( rw == RNOP ){
364 printf( "RNOP" );
365 return;
366 }
367
368 flag = 0;
369 for( i=0; rwnames[i]; ++i ){
370 if( rw & (1<<i) ){
371 if( flag ) printf( "|" );
372 ++flag;
373 printf( rwnames[i] );
374 }
375 }
376 }
377# endif
378
379reclaim( p, rw, cookie ) NODE *p; {
380 register NODE **qq;
381 register NODE *q;
382 register i;
383 NODE *recres[5];
384 struct respref *r;
385
386 /* get back stuff */
387
388# ifndef BUG3
389 if( rdebug ){
390 printf( "reclaim( %o, ", p );
391 rwprint( rw );
392 printf( ", " );
393 prcook( cookie );
394 printf( " )\n" );
395 }
396# endif
397
398 if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return; /* do nothing */
399
400 walkf( p, recl2 );
401
402 if( callop(p->in.op) ){
403 /* check that all scratch regs are free */
404 callchk(p); /* ordinarily, this is the same as allchk() */
405 }
406
407 if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
408 tfree(p);
409 return;
410 }
411
412 /* handle condition codes specially */
413
414 if( (cookie & FORCC) && (rw&RESCC)) {
415 /* result is CC register */
416 tfree(p);
417 p->in.op = CCODES;
418 p->tn.lval = 0;
419 p->tn.rval = 0;
420 return;
421 }
422
423 /* locate results */
424
425 qq = recres;
426
427 if( rw&RLEFT) *qq++ = getlr( p, 'L' );;
428 if( rw&RRIGHT ) *qq++ = getlr( p, 'R' );
429 if( rw&RESC1 ) *qq++ = &resc[0];
430 if( rw&RESC2 ) *qq++ = &resc[1];
431 if( rw&RESC3 ) *qq++ = &resc[2];
432
433 if( qq == recres ){
434 cerror( "illegal reclaim");
435 }
436
437 *qq = NIL;
438
439 /* now, select the best result, based on the cookie */
440
441 for( r=respref; r->cform; ++r ){
442 if( cookie & r->cform ){
443 for( qq=recres; (q= *qq) != NIL; ++qq ){
444 if( tshape( q, r->mform ) ) goto gotit;
445 }
446 }
447 }
448
449 /* we can't do it; die */
450 cerror( "cannot reclaim");
451
452 gotit:
453
454 if( p->in.op == STARG ) p = p->in.left; /* STARGs are still STARGS */
455
456 q->in.type = p->in.type; /* to make multi-register allocations work */
457 /* maybe there is a better way! */
458 q = tcopy(q);
459
460 tfree(p);
461
462 p->in.op = q->in.op;
463 p->tn.lval = q->tn.lval;
464 p->tn.rval = q->tn.rval;
465#ifdef FLEXNAMES
466 p->in.name = q->in.name;
467#ifdef ONEPASS
468 p->in.stalign = q->in.stalign;
469#endif
470#else
471 for( i=0; i<NCHNAM; ++i )
472 p->in.name[i] = q->in.name[i];
473#endif
474
475 q->in.op = FREE;
476
477 /* if the thing is in a register, adjust the type */
478
479 switch( p->in.op ){
480
481 case REG:
482 if( !rtyflg ){
483 /* the C language requires intermediate results to change type */
484 /* this is inefficient or impossible on some machines */
485 /* the "T" command in match supresses this type changing */
486 if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT;
487 else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED;
262eaf56 488#if !defined(FORT) && !defined(SPRECC)
e91423bb 489 else if( p->in.type == FLOAT ) p->in.type = DOUBLE;
bd4e35d4 490#endif
e91423bb
RC
491 }
492 if( ! (p->in.rall & MUSTDO ) ) return; /* unless necessary, ignore it */
493 i = p->in.rall & ~MUSTDO;
494 if( i & NOPREF ) return;
495 if( i != p->tn.rval ){
496 if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){
497 cerror( "faulty register move" );
498 }
499 rbusy( i, p->in.type );
500 rfree( p->tn.rval, p->in.type );
501 rmove( i, p->tn.rval, p->in.type );
502 p->tn.rval = i;
503 }
504
505 case OREG:
506 if( p->in.op == REG || !R2TEST(p->tn.rval) ) {
507 if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror( "potential register overwrite");
508 }
509 else
510 if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) )
511 || (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) )
512 cerror( "potential register overwrite");
513 }
514
515 }
516
3464f46e 517#ifndef ncopy
e91423bb
RC
518ncopy( q, p ) NODE *p, *q; {
519 /* copy the contents of p into q, without any feeling for
520 the contents */
521 /* this code assume that copying rval and lval does the job;
522 in general, it might be necessary to special case the
523 operator types */
524 register i;
525
526 q->in.op = p->in.op;
527 q->in.rall = p->in.rall;
528 q->in.type = p->in.type;
529 q->tn.lval = p->tn.lval;
530 q->tn.rval = p->tn.rval;
531#ifdef FLEXNAMES
532 q->in.name = p->in.name;
533#ifdef ONEPASS
534 q->in.stalign = p->in.stalign;
535#endif
536#else
537 for( i=0; i<NCHNAM; ++i ) q->in.name[i] = p->in.name[i];
538#endif
539
540 }
3464f46e 541#endif
e91423bb
RC
542
543NODE *
544tcopy( p ) register NODE *p; {
545 /* make a fresh copy of p */
546
547 register NODE *q;
548 register r;
549
550 ncopy( q=talloc(), p );
551
552 r = p->tn.rval;
553 if( p->in.op == REG ) rbusy( r, p->in.type );
554 else if( p->in.op == OREG ) {
555 if( R2TEST(r) ){
556 if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT );
557 rbusy( R2UPK2(r), INT );
558 }
559 else {
560 rbusy( r, PTR+INT );
561 }
562 }
563
564 switch( optype(q->in.op) ){
565
566 case BITYPE:
567 q->in.right = tcopy(p->in.right);
568 case UTYPE:
569 q->in.left = tcopy(p->in.left);
570 }
571
572 return(q);
573 }
574
575allchk(){
576 /* check to ensure that all register are free */
577
578 register i;
579
580 REGLOOP(i){
581 if( istreg(i) && busy[i] ){
582 cerror( "register allocation error");
583 }
584 }
585
586 }