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