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