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