|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)code.c 1.6 (Berkeley) 5/31/88";
3: #endif
4:
5: # include "pass1.h"
6: # include <sys/types.h>
7: # include <a.out.h>
8: # include <stab.h>
9:
10: int proflg = 0; /* are we generating profiling code? */
11: int strftn = 0; /* is the current function one which returns a value */
12: int gdebug;
13: int fdefflag; /* are we within a function definition ? */
14: #ifndef STABDOT
15: char NULLNAME[8];
16: #endif
17: int labelno;
18:
19: # define putstr(s) fputs((s), stdout)
20:
21: branch( n ){
22: /* output a branch to label n */
23: /* exception is an ordinary function branching to retlab: then, return */
24: if( nerrors ) return;
25: if( n == retlab && !strftn ){
26: register TWORD t;
27: register r;
28: /* set number of regs in assem comment field */
29: /* so optimizers can do a better job */
30: r = 0;
31: if( retstat & RETVAL ){ /* the function rets a val somewhere */
32: t = (&stab[curftn])->stype;
33: t = DECREF(t);
34: r++; /* it is at least one */
35: if(t == DOUBLE)
36: r++; /* it takes two */
37: } else /* the fn does not ret a val */
38: r = 2;
39: printf( " ret#%d\n", r );
40: }
41: else printf( " jbr L%d\n", n );
42: }
43:
44: int lastloc = { -1 };
45:
46: short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
47: #define LOG2SZ 9
48:
49: defalign(n) {
50: /* cause the alignment to become a multiple of n */
51: n /= SZCHAR;
52: if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
53: }
54:
55: locctr( l ){
56: register temp;
57: /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
58:
59: if( l == lastloc ) return(l);
60: temp = lastloc;
61: lastloc = l;
62: if( nerrors ) return(temp);
63: switch( l ){
64:
65: case PROG:
66: putstr( " .text\n" );
67: psline();
68: break;
69:
70: case DATA:
71: case ADATA:
72: putstr( " .data\n" );
73: break;
74:
75: case STRNG:
76: putstr( " .data 1\n" );
77: break;
78:
79: case ISTRNG:
80: putstr( " .data 2\n" );
81: break;
82:
83: case STAB:
84: putstr( " .stab\n" );
85: break;
86:
87: default:
88: cerror( "illegal location counter" );
89: }
90:
91: return( temp );
92: }
93:
94: deflab( n ){
95: /* output something to define the current position as label n */
96: if (nerrors) return;
97: printf( "L%d:\n", n );
98: }
99:
100: int crslab = 10;
101:
102: getlab(){
103: /* return a number usable for a label */
104: return( ++crslab );
105: }
106:
107:
108: efcode(){
109: /* code for the end of a function */
110:
111: if( strftn ){ /* copy output (in R2) to caller */
112: register NODE *l, *r;
113: register struct symtab *p;
114: register TWORD t;
115: register int i;
116:
117: p = &stab[curftn];
118: t = p->stype;
119: t = DECREF(t);
120:
121: deflab( retlab );
122:
123: i = getlab(); /* label for return area */
124: #ifndef LCOMM
125: putstr(" .data\n" );
126: putstr(" .align 2\n" );
127: printf("L%d: .space %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
128: putstr(" .text\n" );
129: #else
130: { int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR;
131: if (sz % (SZINT/SZCHAR))
132: sz += (SZINT/SZCHAR) - (sz % (SZINT/SZCHAR));
133: printf(" .lcomm L%d,%d\n", i, sz);
134: }
135: #endif
136: psline();
137: printf(" movab L%d,r1\n", i);
138:
139: reached = 1;
140: l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
141: l->tn.rval = 1; /* R1 */
142: l->tn.lval = 0; /* no offset */
143: r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
144: r->tn.rval = 0; /* R0 */
145: r->tn.lval = 0;
146: l = buildtree( UNARY MUL, l, NIL );
147: r = buildtree( UNARY MUL, r, NIL );
148: l = buildtree( ASSIGN, l, r );
149: l->in.op = FREE;
150: ecomp( l->in.left );
151: printf( " movab L%d,r0\n", i );
152: /* turn off strftn flag, so return sequence will be generated */
153: strftn = 0;
154: }
155: branch( retlab );
156: p2bend();
157: fdefflag = 0;
158: }
159:
160: int ftlab1, ftlab2;
161:
162: bfcode( a, n ) int a[]; {
163: /* code for the beginning of a function; a is an array of
164: indices in stab for the arguments; n is the number */
165: register i;
166: register temp;
167: register struct symtab *p;
168: int off;
169: #ifdef REG_CHAR
170: char *toreg();
171: #endif
172: char *rname();
173:
174: if( nerrors ) return;
175: (void) locctr( PROG );
176: p = &stab[curftn];
177: putstr( " .align 1\n");
178: defnam( p );
179: temp = p->stype;
180: temp = DECREF(temp);
181: strftn = (temp==STRTY) || (temp==UNIONTY);
182:
183: retlab = getlab();
184:
185: /* routine prolog */
186:
187: printf( " .word L%d\n", ftnno);
188: ftlab1 = getlab();
189: ftlab2 = getlab();
190: printf( " jbr L%d\n", ftlab1);
191: printf( "L%d:\n", ftlab2);
192: if( proflg ) { /* profile code */
193: i = getlab();
194: printf(" pushl $L%d\n", i);
195: putstr(" callf $8,mcount\n");
196: putstr(" .data\n");
197: putstr(" .align 2\n");
198: printf("L%d: .long 0\n", i);
199: putstr(" .text\n");
200: psline();
201: }
202:
203: off = ARGINIT;
204:
205: for( i=0; i<n; ++i ){
206: p = &stab[a[i]];
207: if( p->sclass == REGISTER ){
208: temp = p->offset; /* save register number */
209: p->sclass = PARAM; /* forget that it is a register */
210: p->offset = NOOFFSET;
211: (void) oalloc( p, &off );
212: #ifdef REG_CHAR
213: printf( " %s", toreg(p->stype)) );
214: #else
215: putstr(" movl");
216: #endif
217: printf( " %d(fp),%s\n", p->offset/SZCHAR, rname(temp) );
218: p->offset = temp; /* remember register number */
219: p->sclass = REGISTER; /* remember that it is a register */
220: #ifdef REG_CHAR
221: temp = p->stype;
222: if( temp==CHAR || temp==SHORT )
223: p->stype = INT;
224: else if( temp==UCHAR || temp==USHORT )
225: p->stype = UNSIGNED;
226: #endif
227: }
228: else if( p->stype == STRTY || p->stype == UNIONTY ) {
229: p->offset = NOOFFSET;
230: if( oalloc( p, &off ) ) cerror( "bad argument" );
231: SETOFF( off, ALSTACK );
232: }
233: else {
234: if( oalloc( p, &off ) ) cerror( "bad argument" );
235: }
236:
237: }
238: if (gdebug && !nerrors) {
239: #ifdef STABDOT
240: pstabdot(N_SLINE, lineno);
241: #else
242: pstab(NULLNAME, N_SLINE);
243: printf("0,%d,LL%d\n", lineno, labelno);
244: printf("LL%d:\n", labelno++);
245: #endif
246: }
247: fdefflag = 1;
248: }
249:
250: bccode(){ /* called just before the first executable statment */
251: /* by now, the automatics and register variables are allocated */
252: SETOFF( autooff, SZINT );
253: /* set aside store area offset */
254: p2bbeg( autooff, regvar );
255: }
256:
257: /*ARGSUSED*/
258: ejobcode( flag ){
259: /* called just before final exit */
260: /* flag is 1 if errors, 0 if none */
261: }
262:
263: #ifndef aobeg
264: aobeg(){
265: /* called before removing automatics from stab */
266: }
267: #endif aobeg
268:
269: #ifndef aocode
270: /*ARGSUSED*/
271: aocode(p) struct symtab *p; {
272: /* called when automatic p removed from stab */
273: }
274: #endif aocode
275:
276: #ifndef aoend
277: aoend(){
278: /* called after removing all automatics from stab */
279: }
280: #endif aoend
281:
282: defnam( p ) register struct symtab *p; {
283: /* define the current location as the name p->sname */
284:
285: if( p->sclass == EXTDEF ){
286: printf( " .globl %s\n", exname( p->sname ) );
287: }
288: if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
289: else printf( "%s:\n", exname( p->sname ) );
290:
291: }
292:
293: bycode( t, i ){
294: #ifdef ASSTRINGS
295: static int lastoctal = 0;
296: #endif
297:
298: /* put byte i+1 in a string */
299:
300: if ( nerrors ) return;
301: #ifdef ASSTRINGS
302:
303: i &= 077;
304: if ( t < 0 ){
305: if ( i != 0 ) putstr( "\"\n" );
306: } else {
307: if ( i == 0 ) putstr("\t.ascii\t\"");
308: if ( t == '\\' || t == '"'){
309: lastoctal = 0;
310: printf("\\%c", t);
311: }
312: else if ( t < 040 || t >= 0177 ){
313: lastoctal++;
314: printf("\\%o",t);
315: }
316: else if ( lastoctal && '0' <= t && t <= '9' ){
317: lastoctal = 0;
318: printf("\"\n\t.ascii\t\"%c", t );
319: }
320: else
321: {
322: lastoctal = 0;
323: putchar(t);
324: }
325: if ( i == 077 ) putstr("\"\n");
326: }
327: #else
328:
329: i &= 07;
330: if( t < 0 ){ /* end of the string */
331: if( i != 0 ) putchar( '\n' );
332: }
333:
334: else { /* stash byte t into string */
335: if( i == 0 ) putstr( " .byte " );
336: else putchar( ',' );
337: printf( "0x%x", t );
338: if( i == 07 ) putchar( '\n' );
339: }
340: #endif
341: }
342:
343: zecode( n ){
344: /* n integer words of zeros */
345: OFFSZ temp;
346: if( n <= 0 ) return;
347: printf( " .space %d\n", (SZINT/SZCHAR)*n );
348: temp = n;
349: inoff += temp*SZINT;
350: }
351:
352: /*ARGSUSED*/
353: fldal( t ) unsigned t; { /* return the alignment of field of type t */
354: uerror( "illegal field type" );
355: return( ALINT );
356: }
357:
358: /*ARGSUSED*/
359: fldty( p ) struct symtab *p; { /* fix up type of field p */
360: ;
361: }
362:
363: /*ARGSUSED*/
364: where(c){ /* print location of error */
365: /* c is either 'u', 'c', or 'w' */
366: /* GCOS version */
367: fprintf( stderr, "%s, line %d: ", ftitle, lineno );
368: }
369:
370:
371: #ifdef REG_CHAR
372: /* tbl - toreg() returns a pointer to a char string
373: which is the correct "register move" for the passed type
374: */
375: struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
376: {
377: CHAR, "cvtbl",
378: SHORT, "cvtwl",
379: UCHAR, "movzbl",
380: USHORT, "movzwl",
381: 0, "movl"
382: };
383:
384: char
385: *toreg(type)
386: TWORD type;
387: {
388: struct type_move *p;
389:
390: for ( p=toreg_strs; p->fromtype != 0; p++)
391: if (p->fromtype == type) return(p->tostrng);
392:
393: /* type not found, must be a word type */
394: return(p->tostrng);
395: }
396: /* tbl */
397: #endif
398:
399:
400: main( argc, argv ) char *argv[]; {
401: #ifdef BUFSTDERR
402: char errbuf[BUFSIZ];
403: setbuf(stderr, errbuf);
404: #endif
405: return(mainp1( argc, argv ));
406: }
407:
408: struct sw heapsw[SWITSZ]; /* heap for switches */
409:
410: genswitch(p,n) register struct sw *p;{
411: /* p points to an array of structures, each consisting
412: of a constant value and a label.
413: The first is >=0 if there is a default label;
414: its value is the label number
415: The entries p[1] to p[n] are the nontrivial cases
416: */
417: register i;
418: register CONSZ j;
419: register CONSZ unsigned range;
420: register dlab, swlab;
421:
422: if( nerrors ) return;
423: range = p[n].sval-p[1].sval;
424:
425: if( range <= 3*n && n>=4 ){ /* implement a direct switch */
426:
427: swlab = getlab();
428: dlab = p->slab >= 0 ? p->slab : getlab();
429:
430: /* already in r0 */
431: putstr( " casel r0,$" );
432: printf( CONFMT, p[1].sval );
433: putstr(",$");
434: printf( CONFMT, range);
435: printf("\n .align 1\nL%d:\n", swlab);
436: for( i=1,j=p[1].sval; i<=n; j++) {
437: printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
438: swlab);
439: }
440:
441: if( p->slab >= 0 ) branch( dlab );
442: else printf("L%d:\n", dlab);
443: return;
444:
445: }
446:
447: if( n>8 ) { /* heap switch */
448:
449: heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
450: makeheap(p, n, 1); /* build heap */
451:
452: walkheap(1, n); /* produce code */
453:
454: if( p->slab >= 0 )
455: branch( dlab );
456: else
457: printf("L%d:\n", dlab);
458: return;
459: }
460:
461: /* debugging code */
462:
463: /* out for the moment
464: if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
465: */
466:
467: /* simple switch code */
468:
469: for( i=1; i<=n; ++i ){
470: /* already in r0 */
471:
472: putstr( " cmpl r0,$" );
473: printf( CONFMT, p[i].sval );
474: printf( "\n jeql L%d\n", p[i].slab );
475: }
476:
477: if( p->slab>=0 ) branch( p->slab );
478: }
479:
480: makeheap(p, m, n)
481: register struct sw *p;
482: {
483: register int q;
484:
485: q = selectheap(m);
486: heapsw[n] = p[q];
487: if( q>1 ) makeheap(p, q-1, 2*n);
488: if( q<m ) makeheap(p+q, m-q, 2*n+1);
489: }
490:
491: selectheap(m) {
492: register int l,i,k;
493:
494: for(i=1; ; i*=2)
495: if( (i-1) > m ) break;
496: l = ((k = i/2 - 1) + 1)/2;
497: return( l + (m-k < l ? m-k : l));
498: }
499:
500: walkheap(start, limit)
501: {
502: int label;
503:
504:
505: if( start > limit ) return;
506: putstr( " cmpl r0,$" );
507: printf( CONFMT, heapsw[start].sval);
508: printf("\n jeql L%d\n", heapsw[start].slab);
509: if( (2*start) > limit ) {
510: printf(" jbr L%d\n", heapsw[0].slab);
511: return;
512: }
513: if( (2*start+1) <= limit ) {
514: label = getlab();
515: printf(" jgtr L%d\n", label);
516: } else
517: printf(" jgtr L%d\n", heapsw[0].slab);
518: walkheap( 2*start, limit);
519: if( (2*start+1) <= limit ) {
520: printf("L%d:\n", label);
521: walkheap( 2*start+1, limit);
522: }
523: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.