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