xref: /original-bsd/old/pcc/mip/allo.c (revision 9369a801)
1fa7a4468Sralph #ifndef lint
2*9369a801Sdonn static char *sccsid ="@(#)allo.c	4.10 (Berkeley) 12/09/87";
3fa7a4468Sralph #endif lint
4fa7a4468Sralph 
50b152873Sralph # include "pass2.h"
6140ba13dSralph 
7140ba13dSralph NODE resc[3];
8140ba13dSralph 
9140ba13dSralph int busy[REGSZ];
10140ba13dSralph 
11140ba13dSralph int maxa, mina, maxb, minb;
12140ba13dSralph 
13140ba13dSralph # ifndef ALLO0
allo0()14140ba13dSralph allo0(){ /* free everything */
15140ba13dSralph 
16140ba13dSralph 	register i;
17140ba13dSralph 
18140ba13dSralph 	maxa = maxb = -1;
19140ba13dSralph 	mina = minb = 0;
20140ba13dSralph 
21140ba13dSralph 	REGLOOP(i){
22140ba13dSralph 		busy[i] = 0;
23140ba13dSralph 		if( rstatus[i] & STAREG ){
24140ba13dSralph 			if( maxa<0 ) mina = i;
25140ba13dSralph 			maxa = i;
26140ba13dSralph 			}
27140ba13dSralph 		if( rstatus[i] & STBREG ){
28140ba13dSralph 			if( maxb<0 ) minb = i;
29140ba13dSralph 			maxb = i;
30140ba13dSralph 			}
31140ba13dSralph 		}
32140ba13dSralph 	}
33140ba13dSralph # endif
34140ba13dSralph 
35140ba13dSralph # ifndef ALLO
allo(p,q)36140ba13dSralph allo( p, q ) NODE *p; struct optab *q; {
37140ba13dSralph 
38140ba13dSralph 	register n, i, j;
39140ba13dSralph 	int either;
40140ba13dSralph 
41140ba13dSralph 	n = q->needs;
42140ba13dSralph 	either = ( EITHER & n );
43140ba13dSralph 	i = 0;
44140ba13dSralph 
45140ba13dSralph 	while( n & NACOUNT ){
46140ba13dSralph 		resc[i].in.op = REG;
477fd72f7dSsam 		resc[i].tn.rval = freereg( p, n&(NAMASK|NEVEN) );
48140ba13dSralph 		resc[i].tn.lval = 0;
49140ba13dSralph #ifdef FLEXNAMES
50140ba13dSralph 		resc[i].in.name = "";
51140ba13dSralph #else
52140ba13dSralph 		resc[i].in.name[0] = '\0';
53140ba13dSralph #endif
547fd72f7dSsam 		n &= ~NEVEN;		/* only used for first need */
55140ba13dSralph 		n -= NAREG;
56140ba13dSralph 		++i;
57140ba13dSralph 		}
58140ba13dSralph 
59140ba13dSralph 	if (either) { /* all or nothing at all */
60140ba13dSralph 		for( j = 0; j < i; j++ )
61140ba13dSralph 			if( resc[j].tn.rval < 0 ) { /* nothing */
62140ba13dSralph 				i = 0;
63140ba13dSralph 				break;
64140ba13dSralph 				}
65140ba13dSralph 		if( i != 0 ) goto ok; /* all */
66140ba13dSralph 		}
67140ba13dSralph 
68140ba13dSralph 	while( n & NBCOUNT ){
69140ba13dSralph 		resc[i].in.op = REG;
70140ba13dSralph 		resc[i].tn.rval = freereg( p, n&NBMASK );
71140ba13dSralph 		resc[i].tn.lval = 0;
72140ba13dSralph #ifdef FLEXNAMES
73140ba13dSralph 		resc[i].in.name = "";
74140ba13dSralph #else
75140ba13dSralph 		resc[i].in.name[0] = '\0';
76140ba13dSralph #endif
77140ba13dSralph 		n -= NBREG;
78140ba13dSralph 		++i;
79140ba13dSralph 		}
80140ba13dSralph 	if (either) { /* all or nothing at all */
81140ba13dSralph 		for( j = 0; j < i; j++ )
82140ba13dSralph 			if( resc[j].tn.rval < 0 ) { /* nothing */
83140ba13dSralph 				i = 0;
84140ba13dSralph 				break;
85140ba13dSralph 				}
86140ba13dSralph 		if( i != 0 ) goto ok; /* all */
87140ba13dSralph 		}
88140ba13dSralph 
89140ba13dSralph 	if( n & NTMASK ){
90140ba13dSralph 		resc[i].in.op = OREG;
91140ba13dSralph 		resc[i].tn.rval = TMPREG;
92140ba13dSralph 		if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){
93140ba13dSralph 			resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT );
94140ba13dSralph 			}
95140ba13dSralph 		else {
96140ba13dSralph 			resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP );
97140ba13dSralph 			}
98140ba13dSralph #ifdef FLEXNAMES
99140ba13dSralph 		resc[i].in.name = "";
100140ba13dSralph #else
101140ba13dSralph 		resc[i].in.name[0] = '\0';
102140ba13dSralph #endif
103140ba13dSralph 
104140ba13dSralph 		resc[i].tn.lval = BITOOR(resc[i].tn.lval);
105140ba13dSralph 		++i;
106140ba13dSralph 		}
107140ba13dSralph 
108140ba13dSralph 	/* turn off "temporarily busy" bit */
109140ba13dSralph 
110140ba13dSralph 	ok:
111140ba13dSralph 	REGLOOP(j){
112140ba13dSralph 		busy[j] &= ~TBUSY;
113140ba13dSralph 		}
114140ba13dSralph 
115140ba13dSralph 	for( j=0; j<i; ++j ) if( resc[j].tn.rval < 0 ) return(0);
116140ba13dSralph 	return(1);
117140ba13dSralph 
118140ba13dSralph 	}
119140ba13dSralph # endif
120140ba13dSralph 
121140ba13dSralph extern unsigned int offsz;
freetemp(k)122140ba13dSralph freetemp( k ){ /* allocate k integers worth of temp space */
123140ba13dSralph 	/* we also make the convention that, if the number of words is more than 1,
124140ba13dSralph 	/* it must be aligned for storing doubles... */
125140ba13dSralph 
126140ba13dSralph # ifndef BACKTEMP
127140ba13dSralph 	int t;
128140ba13dSralph 
129140ba13dSralph 	if( k>1 ){
130140ba13dSralph 		SETOFF( tmpoff, ALDOUBLE );
131140ba13dSralph 		}
132140ba13dSralph 
133140ba13dSralph 	t = tmpoff;
134140ba13dSralph 	tmpoff += k*SZINT;
135140ba13dSralph 	if( tmpoff > maxoff ) maxoff = tmpoff;
136140ba13dSralph 	if( tmpoff >= offsz )
137140ba13dSralph 		cerror( "stack overflow" );
138140ba13dSralph 	if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
139140ba13dSralph 	return(t);
140140ba13dSralph 
141140ba13dSralph # else
142140ba13dSralph 	tmpoff += k*SZINT;
143140ba13dSralph 	if( k>1 ) {
144140ba13dSralph 		SETOFF( tmpoff, ALDOUBLE );
145140ba13dSralph 		}
146140ba13dSralph 	if( tmpoff > maxoff ) maxoff = tmpoff;
147140ba13dSralph 	if( tmpoff >= offsz )
148140ba13dSralph 		cerror( "stack overflow" );
149140ba13dSralph 	if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
150140ba13dSralph 	return( -tmpoff );
151140ba13dSralph # endif
152140ba13dSralph 	}
153140ba13dSralph 
freereg(p,n)154140ba13dSralph freereg( p, n ) NODE *p; {
155140ba13dSralph 	/* allocate a register of type n */
156140ba13dSralph 	/* p gives the type, if floating */
157140ba13dSralph 
158140ba13dSralph 	register j;
159140ba13dSralph 
160140ba13dSralph 	/* not general; means that only one register (the result) OK for call */
161140ba13dSralph 	if( callop(p->in.op) ){
162140ba13dSralph 		j = callreg(p);
163140ba13dSralph 		if( usable( p, n, j ) ) return( j );
164140ba13dSralph 		/* have allocated callreg first */
165140ba13dSralph 		}
166140ba13dSralph 	j = p->in.rall & ~MUSTDO;
167140ba13dSralph 	if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */
168140ba13dSralph 		return( j );
169140ba13dSralph 		}
170140ba13dSralph 	if( n&NAMASK ){
171140ba13dSralph 		for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){
172140ba13dSralph 			if( usable(p,n,j) ){
173140ba13dSralph 				return( j );
174140ba13dSralph 				}
175140ba13dSralph 			}
176140ba13dSralph 		}
177140ba13dSralph 	else if( n &NBMASK ){
178140ba13dSralph 		for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){
179140ba13dSralph 			if( usable(p,n,j) ){
180140ba13dSralph 				return(j);
181140ba13dSralph 				}
182140ba13dSralph 			}
183140ba13dSralph 		}
184140ba13dSralph 
185140ba13dSralph 	return( -1 );
186140ba13dSralph 	}
187140ba13dSralph 
188140ba13dSralph # ifndef USABLE
usable(p,n,r)189140ba13dSralph usable( p, n, r ) NODE *p; {
190140ba13dSralph 	/* decide if register r is usable in tree p to satisfy need n */
191140ba13dSralph 
192140ba13dSralph 	/* checks, for the moment */
193140ba13dSralph 	if( !istreg(r) ) cerror( "usable asked about nontemp register" );
194140ba13dSralph 
195*9369a801Sdonn 	if( ISBUSY(r) ) return(0);
196140ba13dSralph 	if( isbreg(r) ){
197140ba13dSralph 		if( n&NAMASK ) return(0);
198140ba13dSralph 		}
199140ba13dSralph 	else {
200140ba13dSralph 		if( n & NBMASK ) return(0);
201140ba13dSralph 		}
202450ef15bSralph 	/*
203b08aa39fSdonn 	 * Some special cases that require register pairs...
204b08aa39fSdonn 	 * Have to check for ==, <=, etc. because the result is type int
205b08aa39fSdonn 	 * but need a register pair temp if either side is wide.
206b08aa39fSdonn 	 * For +=, *= etc. where lhs is narrow and rhs is wide, the temp
207b08aa39fSdonn 	 * register must be wide.
208450ef15bSralph 	 */
209b08aa39fSdonn 	if( (n&NAMASK) &&
2107fd72f7dSsam 	    (szty(p->in.type) == 2 || (n&NEVEN) ||
211b08aa39fSdonn 	     (logop(p->in.op) && (szty(p->in.left->in.type) == 2 ||
212b08aa39fSdonn 	      szty(p->in.right->in.type) == 2)) ||
213b08aa39fSdonn 	     (asgop(p->in.op) && szty(p->in.right->in.type) == 2 &&
214b08aa39fSdonn 	      szty(p->in.left->in.type) == 1))
215b08aa39fSdonn 	){
2162ed9fee1Sralph #ifndef NOEVENODD
217140ba13dSralph 		if( r&01 ) return(0);
2182ed9fee1Sralph #endif
219140ba13dSralph 		if( !istreg(r+1) ) return( 0 );
220140ba13dSralph 		if( busy[r+1] > 1 ) return( 0 );
221140ba13dSralph 		if( busy[r] == 0 && busy[r+1] == 0  ||
222*9369a801Sdonn 		    (busy[r+1] == 0 || (busy[r] & PBUSY)) &&
223*9369a801Sdonn 			shareit( p, r, n ) ||
224140ba13dSralph 		    busy[r] == 0 && shareit( p, r+1, n ) ){
225140ba13dSralph 			busy[r] |= TBUSY;
226140ba13dSralph 			busy[r+1] |= TBUSY;
227140ba13dSralph 			return(1);
228140ba13dSralph 			}
229140ba13dSralph 		else return(0);
230140ba13dSralph 		}
231140ba13dSralph 	if( busy[r] == 0 ) {
232140ba13dSralph 		busy[r] |= TBUSY;
233140ba13dSralph 		return(1);
234140ba13dSralph 		}
235140ba13dSralph 
236140ba13dSralph 	/* busy[r] is 1: is there chance for sharing */
237140ba13dSralph 	return( shareit( p, r, n ) );
238140ba13dSralph 
239140ba13dSralph 	}
240140ba13dSralph # endif
241140ba13dSralph 
shareit(p,r,n)242140ba13dSralph shareit( p, r, n ) NODE *p; {
243140ba13dSralph 	/* can we make register r available by sharing from p
244140ba13dSralph 	   given that the need is n */
245140ba13dSralph 	if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1);
246140ba13dSralph 	if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1);
247140ba13dSralph 	return(0);
248140ba13dSralph 	}
249140ba13dSralph 
ushare(p,f,r)250140ba13dSralph ushare( p, f, r ) NODE *p; {
251140ba13dSralph 	/* can we find a register r to share on the left or right
252140ba13dSralph 		(as f=='L' or 'R', respectively) of p */
253140ba13dSralph 	p = getlr( p, f );
254140ba13dSralph 	if( p->in.op == UNARY MUL ) p = p->in.left;
255140ba13dSralph 	if( p->in.op == OREG ){
256140ba13dSralph 		if( R2TEST(p->tn.rval) ){
257140ba13dSralph 			return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) );
258140ba13dSralph 			}
259140ba13dSralph 		else return( r == p->tn.rval );
260140ba13dSralph 		}
261140ba13dSralph 	if( p->in.op == REG ){
262140ba13dSralph 		return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) );
263140ba13dSralph 		}
264140ba13dSralph 	return(0);
265140ba13dSralph 	}
266140ba13dSralph 
recl2(p)267140ba13dSralph recl2( p ) register NODE *p; {
268140ba13dSralph 	register r = p->tn.rval;
269140ba13dSralph #ifndef OLD
270140ba13dSralph 	int op = p->in.op;
271140ba13dSralph 	if (op == REG && r >= REGSZ)
272140ba13dSralph 		op = OREG;
273140ba13dSralph 	if( op == REG ) rfree( r, p->in.type );
274140ba13dSralph 	else if( op == OREG ) {
275140ba13dSralph 		if( R2TEST( r ) ) {
276140ba13dSralph 			if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
277140ba13dSralph 			rfree( R2UPK2( r ), INT );
278140ba13dSralph 			}
279140ba13dSralph 		else {
280140ba13dSralph 			rfree( r, PTR+INT );
281140ba13dSralph 			}
282140ba13dSralph 		}
283140ba13dSralph #else
284140ba13dSralph 	if( p->in.op == REG ) rfree( r, p->in.type );
285140ba13dSralph 	else if( p->in.op == OREG ) {
286140ba13dSralph 		if( R2TEST( r ) ) {
287140ba13dSralph 			if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
288140ba13dSralph 			rfree( R2UPK2( r ), INT );
289140ba13dSralph 			}
290140ba13dSralph 		else {
291140ba13dSralph 			rfree( r, PTR+INT );
292140ba13dSralph 			}
293140ba13dSralph 		}
294140ba13dSralph #endif
295140ba13dSralph 	}
296140ba13dSralph 
297140ba13dSralph int rdebug = 0;
298140ba13dSralph 
299140ba13dSralph # ifndef RFREE
rfree(r,t)300140ba13dSralph rfree( r, t ) TWORD t; {
301140ba13dSralph 	/* mark register r free, if it is legal to do so */
302140ba13dSralph 	/* t is the type */
303140ba13dSralph 
304140ba13dSralph # ifndef BUG3
305140ba13dSralph 	if( rdebug ){
306140ba13dSralph 		printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
307140ba13dSralph 		}
308140ba13dSralph # endif
309140ba13dSralph 
310140ba13dSralph 	if( istreg(r) ){
311140ba13dSralph 		if( --busy[r] < 0 ) cerror( "register overfreed");
312*9369a801Sdonn 		if( busy[r] == PBUSY )
313*9369a801Sdonn 			busy[r] = 0;
314140ba13dSralph 		if( szty(t) == 2 ){
3152ed9fee1Sralph #ifdef NOEVENODD
3162ed9fee1Sralph 			if( istreg(r) ^ istreg(r+1) ) cerror( "illegal free" );
3172ed9fee1Sralph #else
318140ba13dSralph 			if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
3192ed9fee1Sralph #endif
320140ba13dSralph 			if( --busy[r+1] < 0 ) cerror( "register overfreed" );
321140ba13dSralph 			}
322140ba13dSralph 		}
323140ba13dSralph 	}
324140ba13dSralph # endif
325140ba13dSralph 
326140ba13dSralph # ifndef RBUSY
rbusy(r,t)327140ba13dSralph rbusy(r,t) TWORD t; {
328140ba13dSralph 	/* mark register r busy */
329140ba13dSralph 	/* t is the type */
330140ba13dSralph 
331140ba13dSralph # ifndef BUG3
332140ba13dSralph 	if( rdebug ){
333140ba13dSralph 		printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
334140ba13dSralph 		}
335140ba13dSralph # endif
336140ba13dSralph 
337140ba13dSralph 	if( istreg(r) ) ++busy[r];
338140ba13dSralph 	if( szty(t) == 2 ){
339*9369a801Sdonn 		if( istreg(r+1) ) {
340*9369a801Sdonn 			++busy[r+1];
341*9369a801Sdonn 			busy[r] |= PBUSY;
342*9369a801Sdonn 			}
3432ed9fee1Sralph #ifdef NOEVENODD
3442ed9fee1Sralph 		if( istreg(r) ^ istreg(r+1) ) cerror( "illegal register pair freed" );
3452ed9fee1Sralph #else
346140ba13dSralph 		if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
3472ed9fee1Sralph #endif
348140ba13dSralph 		}
349140ba13dSralph 	}
350140ba13dSralph # endif
351140ba13dSralph 
352140ba13dSralph # ifndef BUG3
rwprint(rw)353140ba13dSralph rwprint( rw ){ /* print rewriting rule */
354140ba13dSralph 	register i, flag;
355140ba13dSralph 	static char * rwnames[] = {
356140ba13dSralph 
357140ba13dSralph 		"RLEFT",
358140ba13dSralph 		"RRIGHT",
359140ba13dSralph 		"RESC1",
360140ba13dSralph 		"RESC2",
361140ba13dSralph 		"RESC3",
362140ba13dSralph 		0,
363140ba13dSralph 		};
364140ba13dSralph 
365140ba13dSralph 	if( rw == RNULL ){
366140ba13dSralph 		printf( "RNULL" );
367140ba13dSralph 		return;
368140ba13dSralph 		}
369140ba13dSralph 
370140ba13dSralph 	if( rw == RNOP ){
371140ba13dSralph 		printf( "RNOP" );
372140ba13dSralph 		return;
373140ba13dSralph 		}
374140ba13dSralph 
375140ba13dSralph 	flag = 0;
376140ba13dSralph 	for( i=0; rwnames[i]; ++i ){
377140ba13dSralph 		if( rw & (1<<i) ){
378140ba13dSralph 			if( flag ) printf( "|" );
379140ba13dSralph 			++flag;
380140ba13dSralph 			printf( rwnames[i] );
381140ba13dSralph 			}
382140ba13dSralph 		}
383140ba13dSralph 	}
384140ba13dSralph # endif
385140ba13dSralph 
reclaim(p,rw,cookie)386140ba13dSralph reclaim( p, rw, cookie ) NODE *p; {
387140ba13dSralph 	register NODE **qq;
388140ba13dSralph 	register NODE *q;
389140ba13dSralph 	register i;
390140ba13dSralph 	NODE *recres[5];
391140ba13dSralph 	struct respref *r;
392140ba13dSralph 
393140ba13dSralph 	/* get back stuff */
394140ba13dSralph 
395140ba13dSralph # ifndef BUG3
396140ba13dSralph 	if( rdebug ){
397140ba13dSralph 		printf( "reclaim( %o, ", p );
398140ba13dSralph 		rwprint( rw );
399140ba13dSralph 		printf( ", " );
400140ba13dSralph 		prcook( cookie );
401140ba13dSralph 		printf( " )\n" );
402140ba13dSralph 		}
403140ba13dSralph # endif
404140ba13dSralph 
405140ba13dSralph 	if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return;  /* do nothing */
406140ba13dSralph 
407140ba13dSralph 	walkf( p, recl2 );
408140ba13dSralph 
409140ba13dSralph 	if( callop(p->in.op) ){
410140ba13dSralph 		/* check that all scratch regs are free */
411140ba13dSralph 		callchk(p);  /* ordinarily, this is the same as allchk() */
412140ba13dSralph 		}
413140ba13dSralph 
414140ba13dSralph 	if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
415140ba13dSralph 		tfree(p);
416140ba13dSralph 		return;
417140ba13dSralph 		}
418140ba13dSralph 
419140ba13dSralph 	/* handle condition codes specially */
420140ba13dSralph 
421140ba13dSralph 	if( (cookie & FORCC) && (rw&RESCC)) {
422140ba13dSralph 		/* result is CC register */
423140ba13dSralph 		tfree(p);
424140ba13dSralph 		p->in.op = CCODES;
425140ba13dSralph 		p->tn.lval = 0;
426140ba13dSralph 		p->tn.rval = 0;
427140ba13dSralph 		return;
428140ba13dSralph 		}
429140ba13dSralph 
430140ba13dSralph 	/* locate results */
431140ba13dSralph 
432140ba13dSralph 	qq = recres;
433140ba13dSralph 
434140ba13dSralph 	if( rw&RLEFT) *qq++ = getlr( p, 'L' );;
435140ba13dSralph 	if( rw&RRIGHT ) *qq++ = getlr( p, 'R' );
436140ba13dSralph 	if( rw&RESC1 ) *qq++ = &resc[0];
437140ba13dSralph 	if( rw&RESC2 ) *qq++ = &resc[1];
438140ba13dSralph 	if( rw&RESC3 ) *qq++ = &resc[2];
439140ba13dSralph 
440140ba13dSralph 	if( qq == recres ){
441140ba13dSralph 		cerror( "illegal reclaim");
442140ba13dSralph 		}
443140ba13dSralph 
444140ba13dSralph 	*qq = NIL;
445140ba13dSralph 
446140ba13dSralph 	/* now, select the best result, based on the cookie */
447140ba13dSralph 
448140ba13dSralph 	for( r=respref; r->cform; ++r ){
449140ba13dSralph 		if( cookie & r->cform ){
450140ba13dSralph 			for( qq=recres; (q= *qq) != NIL; ++qq ){
451140ba13dSralph 				if( tshape( q, r->mform ) ) goto gotit;
452140ba13dSralph 				}
453140ba13dSralph 			}
454140ba13dSralph 		}
455140ba13dSralph 
456140ba13dSralph 	/* we can't do it; die */
457140ba13dSralph 	cerror( "cannot reclaim");
458140ba13dSralph 
459140ba13dSralph 	gotit:
460140ba13dSralph 
461140ba13dSralph 	if( p->in.op == STARG ) p = p->in.left;  /* STARGs are still STARGS */
462140ba13dSralph 
463140ba13dSralph 	q->in.type = p->in.type;  /* to make multi-register allocations work */
464140ba13dSralph 		/* maybe there is a better way! */
465140ba13dSralph 	q = tcopy(q);
466140ba13dSralph 
467140ba13dSralph 	tfree(p);
468140ba13dSralph 
469140ba13dSralph 	p->in.op = q->in.op;
470140ba13dSralph 	p->tn.lval = q->tn.lval;
471140ba13dSralph 	p->tn.rval = q->tn.rval;
472140ba13dSralph #ifdef FLEXNAMES
473140ba13dSralph 	p->in.name = q->in.name;
474140ba13dSralph #ifdef ONEPASS
475140ba13dSralph 	p->in.stalign = q->in.stalign;
476140ba13dSralph #endif
477140ba13dSralph #else
478140ba13dSralph 	for( i=0; i<NCHNAM; ++i )
479140ba13dSralph 		p->in.name[i] = q->in.name[i];
480140ba13dSralph #endif
481140ba13dSralph 
482140ba13dSralph 	q->in.op = FREE;
483140ba13dSralph 
484140ba13dSralph 	/* if the thing is in a register, adjust the type */
485140ba13dSralph 
486140ba13dSralph 	switch( p->in.op ){
487140ba13dSralph 
488140ba13dSralph 	case REG:
489140ba13dSralph 		if( !rtyflg ){
490140ba13dSralph 			/* the C language requires intermediate results to change type */
491140ba13dSralph 			/* this is inefficient or impossible on some machines */
492140ba13dSralph 			/* the "T" command in match supresses this type changing */
493140ba13dSralph 			if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT;
494140ba13dSralph 			else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED;
495fa7a4468Sralph #if !defined(FORT) && !defined(SPRECC)
496140ba13dSralph 			else if( p->in.type == FLOAT ) p->in.type = DOUBLE;
4972ed9fee1Sralph #endif
498140ba13dSralph 			}
499140ba13dSralph 		if( ! (p->in.rall & MUSTDO ) ) return;  /* unless necessary, ignore it */
500140ba13dSralph 		i = p->in.rall & ~MUSTDO;
501140ba13dSralph 		if( i & NOPREF ) return;
502140ba13dSralph 		if( i != p->tn.rval ){
503140ba13dSralph 			if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){
504140ba13dSralph 				cerror( "faulty register move" );
505140ba13dSralph 				}
506140ba13dSralph 			rbusy( i, p->in.type );
507140ba13dSralph 			rfree( p->tn.rval, p->in.type );
508140ba13dSralph 			rmove( i, p->tn.rval, p->in.type );
509140ba13dSralph 			p->tn.rval = i;
510140ba13dSralph 			}
511140ba13dSralph 
512140ba13dSralph 	case OREG:
513140ba13dSralph 		if( p->in.op == REG || !R2TEST(p->tn.rval) ) {
514*9369a801Sdonn 			if( ISBUSY(p->tn.rval) && istreg(p->tn.rval) ) cerror( "potential register overwrite");
515140ba13dSralph 			}
516140ba13dSralph 		else
517*9369a801Sdonn 			if( (R2UPK1(p->tn.rval) != 100 && ISBUSY(R2UPK1(p->tn.rval)) && istreg(R2UPK1(p->tn.rval)) )
518*9369a801Sdonn 				|| (ISBUSY(R2UPK2(p->tn.rval)) && istreg(R2UPK2(p->tn.rval)) ) )
519140ba13dSralph 			   cerror( "potential register overwrite");
520140ba13dSralph 		}
521140ba13dSralph 
522140ba13dSralph 	}
523140ba13dSralph 
5245f56c947Smckusick #ifndef ncopy
ncopy(q,p)525140ba13dSralph ncopy( q, p ) NODE *p, *q; {
526140ba13dSralph 	/* copy the contents of p into q, without any feeling for
527140ba13dSralph 	   the contents */
528140ba13dSralph 	/* this code assume that copying rval and lval does the job;
529140ba13dSralph 	   in general, it might be necessary to special case the
530140ba13dSralph 	   operator types */
531140ba13dSralph 	register i;
532140ba13dSralph 
533140ba13dSralph 	q->in.op = p->in.op;
534140ba13dSralph 	q->in.rall = p->in.rall;
535140ba13dSralph 	q->in.type = p->in.type;
536140ba13dSralph 	q->tn.lval = p->tn.lval;
537140ba13dSralph 	q->tn.rval = p->tn.rval;
538140ba13dSralph #ifdef FLEXNAMES
539140ba13dSralph 	q->in.name = p->in.name;
540140ba13dSralph #ifdef ONEPASS
541140ba13dSralph 	q->in.stalign = p->in.stalign;
542140ba13dSralph #endif
543140ba13dSralph #else
544140ba13dSralph 	for( i=0; i<NCHNAM; ++i ) q->in.name[i]  = p->in.name[i];
545140ba13dSralph #endif
546140ba13dSralph 
547140ba13dSralph 	}
5485f56c947Smckusick #endif
549140ba13dSralph 
550140ba13dSralph NODE *
tcopy(p)551140ba13dSralph tcopy( p ) register NODE *p; {
552140ba13dSralph 	/* make a fresh copy of p */
553140ba13dSralph 
554140ba13dSralph 	register NODE *q;
555140ba13dSralph 	register r;
556140ba13dSralph 
557140ba13dSralph 	ncopy( q=talloc(), p );
558140ba13dSralph 
559140ba13dSralph 	r = p->tn.rval;
560140ba13dSralph 	if( p->in.op == REG ) rbusy( r, p->in.type );
561140ba13dSralph 	else if( p->in.op == OREG ) {
562140ba13dSralph 		if( R2TEST(r) ){
563140ba13dSralph 			if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT );
564140ba13dSralph 			rbusy( R2UPK2(r), INT );
565140ba13dSralph 			}
566140ba13dSralph 		else {
567140ba13dSralph 			rbusy( r, PTR+INT );
568140ba13dSralph 			}
569140ba13dSralph 		}
570140ba13dSralph 
571140ba13dSralph 	switch( optype(q->in.op) ){
572140ba13dSralph 
573140ba13dSralph 	case BITYPE:
574140ba13dSralph 		q->in.right = tcopy(p->in.right);
575140ba13dSralph 	case UTYPE:
576140ba13dSralph 		q->in.left = tcopy(p->in.left);
577140ba13dSralph 		}
578140ba13dSralph 
579140ba13dSralph 	return(q);
580140ba13dSralph 	}
581140ba13dSralph 
allchk()582140ba13dSralph allchk(){
583140ba13dSralph 	/* check to ensure that all register are free */
584140ba13dSralph 
585140ba13dSralph 	register i;
586140ba13dSralph 
587140ba13dSralph 	REGLOOP(i){
588140ba13dSralph 		if( istreg(i) && busy[i] ){
589140ba13dSralph 			cerror( "register allocation error");
590140ba13dSralph 			}
591140ba13dSralph 		}
592140ba13dSralph 
593140ba13dSralph 	}
594