|
|
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, 0x3c| ent_mask[reg_use], ent_mask[reg_use] );
143: /* KLS kludge, under VMS if you use regs 2-5, you must save them. */
144: #endif
145: reg_use = 11;
146: p2bend();
147: fdefflag = 0;
148: }
149:
150: int ftlab1, ftlab2;
151:
152: bfcode( a, n ) int a[]; {
153: /* code for the beginning of a function; a is an array of
154: indices in stab for the arguments; n is the number */
155: register i;
156: register temp;
157: register struct symtab *p;
158: int off;
159: char *toreg();
160:
161: locctr( PROG );
162: p = &stab[curftn];
163: printf( " .align 1\n");
164: defnam( p );
165: temp = p->stype;
166: temp = DECREF(temp);
167: strftn = (temp==STRTY) || (temp==UNIONTY);
168:
169: retlab = getlab();
170:
171: /* routine prolog */
172:
173: printf( " .word L%d\n", ftnno);
174: if (gdebug) {
175: #ifdef STABDOT
176: pstabdot(N_SLINE, lineno);
177: #else
178: pstab(NULLNAME, N_SLINE);
179: printf("0,%d,LL%d\n", lineno, labelno);
180: printf("LL%d:\n", labelno++);
181: #endif
182: }
183: ftlab1 = getlab();
184: ftlab2 = getlab();
185: printf( " jbr L%d\n", ftlab1);
186: printf( "L%d:\n", ftlab2);
187: if( proflg ) { /* profile code */
188: i = getlab();
189: printf(" movab L%d,r0\n", i);
190: printf(" jsb mcount\n");
191: printf(" .data\n");
192: printf(" .align 2\n");
193: printf("L%d: .long 0\n", i);
194: printf(" .text\n");
195: psline();
196: }
197:
198: off = ARGINIT;
199:
200: for( i=0; i<n; ++i ){
201: p = &stab[a[i]];
202: if( p->sclass == REGISTER ){
203: temp = p->offset; /* save register number */
204: p->sclass = PARAM; /* forget that it is a register */
205: p->offset = NOOFFSET;
206: oalloc( p, &off );
207: /*tbl*/ printf( " %s %d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
208: p->offset = temp; /* remember register number */
209: p->sclass = REGISTER; /* remember that it is a register */
210: }
211: else if( p->stype == STRTY || p->stype == UNIONTY ) {
212: p->offset = NOOFFSET;
213: if( oalloc( p, &off ) ) cerror( "bad argument" );
214: SETOFF( off, ALSTACK );
215: }
216: else {
217: if( oalloc( p, &off ) ) cerror( "bad argument" );
218: }
219:
220: }
221: fdefflag = 1;
222: }
223:
224: bccode(){ /* called just before the first executable statment */
225: /* by now, the automatics and register variables are allocated */
226: SETOFF( autooff, SZINT );
227: /* set aside store area offset */
228: p2bbeg( autooff, regvar );
229: reg_use = (reg_use > regvar ? regvar : reg_use);
230: }
231:
232: ejobcode( flag ){
233: /* called just before final exit */
234: /* flag is 1 if errors, 0 if none */
235: }
236:
237: aobeg(){
238: /* called before removing automatics from stab */
239: }
240:
241: aocode(p) struct symtab *p; {
242: /* called when automatic p removed from stab */
243: }
244:
245: aoend(){
246: /* called after removing all automatics from stab */
247: }
248:
249: defnam( p ) register struct symtab *p; {
250: /* define the current location as the name p->sname */
251:
252: if( p->sclass == EXTDEF ){
253: printf( " .globl %s\n", exname( p->sname ) );
254: }
255: if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
256: else printf( "%s:\n", exname( p->sname ) );
257:
258: }
259:
260: bycode( t, i ){
261: #ifdef ASSTRINGS
262: static int lastoctal = 0;
263: #endif
264:
265: /* put byte i+1 in a string */
266:
267: #ifdef ASSTRINGS
268:
269: i &= 077;
270: if ( t < 0 ){
271: if ( i != 0 ) printf( "\"\n" );
272: } else {
273: if ( i == 0 ) printf("\t.ascii\t\"");
274: if ( t == '\\' || t == '"'){
275: lastoctal = 0;
276: printf("\\%c", t);
277: }
278: /*
279: * We escape the colon in strings so that
280: * c2 will, in its infinite wisdom, interpret
281: * the characters preceding the colon as a label.
282: * If we didn't escape the colon, c2 would
283: * throw away any trailing blanks or tabs after
284: * the colon, but reconstruct a assembly
285: * language semantically correct program.
286: * C2 hasn't been taught about strings.
287: */
288: else if ( t == ':' || t < 040 || t >= 0177 ){
289: lastoctal++;
290: printf("\\%o",t);
291: }
292: else if ( lastoctal && '0' <= t && t <= '9' ){
293: lastoctal = 0;
294: printf("\"\n\t.ascii\t\"%c", t );
295: }
296: else
297: {
298: lastoctal = 0;
299: putchar(t);
300: }
301: if ( i == 077 ) printf("\"\n");
302: }
303: #else
304:
305: i &= 07;
306: if( t < 0 ){ /* end of the string */
307: if( i != 0 ) printf( "\n" );
308: }
309:
310: else { /* stash byte t into string */
311: if( i == 0 ) printf( " .byte " );
312: else printf( "," );
313: printf( "0x%x", t );
314: if( i == 07 ) printf( "\n" );
315: }
316: #endif
317: }
318:
319: zecode( n ){
320: /* n integer words of zeros */
321: OFFSZ temp;
322: if( n <= 0 ) return;
323: printf( " .space %d\n", (SZINT/SZCHAR)*n );
324: temp = n;
325: inoff += temp*SZINT;
326: }
327:
328: fldal( t ) unsigned t; { /* return the alignment of field of type t */
329: uerror( "illegal field type" );
330: return( ALINT );
331: }
332:
333: fldty( p ) struct symtab *p; { /* fix up type of field p */
334: ;
335: }
336:
337: where(c){ /* print location of error */
338: /* c is either 'u', 'c', or 'w' */
339: /* GCOS version */
340: fprintf( stderr, "%s, line %d: ", ftitle, lineno );
341: }
342:
343:
344: /* tbl - toreg() returns a pointer to a char string
345: which is the correct "register move" for the passed type
346: */
347: struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
348: {
349: CHAR, "cvtbl",
350: SHORT, "cvtwl",
351: INT, "movl",
352: LONG, "movl",
353: FLOAT, "movf",
354: DOUBLE, "movd",
355: UCHAR, "movzbl",
356: USHORT, "movzwl",
357: UNSIGNED, "movl",
358: ULONG, "movl",
359: -1, ""
360: };
361:
362: char
363: *toreg(type)
364: TWORD type;
365: {
366: struct type_move *p;
367:
368: for ( p=toreg_strs; p->fromtype > 0; p++)
369: if (p->fromtype == type) return(p->tostrng);
370:
371: /* type not found, must be a pointer type */
372: return("movl");
373: }
374: /* tbl */
375:
376:
377: main( argc, argv ) char *argv[]; {
378: #ifdef BUFSTDERR
379: char errbuf[BUFSIZ];
380: setbuf(stderr, errbuf);
381: #endif
382: return(mainp1( argc, argv ));
383: }
384:
385: struct sw heapsw[SWITSZ]; /* heap for switches */
386:
387: genswitch(p,n) register struct sw *p;{
388: /* p points to an array of structures, each consisting
389: of a constant value and a label.
390: The first is >=0 if there is a default label;
391: its value is the label number
392: The entries p[1] to p[n] are the nontrivial cases
393: */
394: register i;
395: register CONSZ j, range;
396: register dlab, swlab;
397:
398: range = p[n].sval-p[1].sval;
399:
400: if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
401:
402: swlab = getlab();
403: dlab = p->slab >= 0 ? p->slab : getlab();
404:
405: /* already in r0 */
406: printf(" casel r0,$%ld,$%ld\n", p[1].sval, range);
407: printf("L%d:\n", swlab);
408: for( i=1,j=p[1].sval; i<=n; j++) {
409: printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
410: swlab);
411: }
412:
413: if( p->slab >= 0 ) branch( dlab );
414: else printf("L%d:\n", dlab);
415: return;
416:
417: }
418:
419: if( n>8 ) { /* heap switch */
420:
421: heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
422: makeheap(p, n, 1); /* build heap */
423:
424: walkheap(1, n); /* produce code */
425:
426: if( p->slab >= 0 )
427: branch( dlab );
428: else
429: printf("L%d:\n", dlab);
430: return;
431: }
432:
433: /* debugging code */
434:
435: /* out for the moment
436: if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
437: */
438:
439: /* simple switch code */
440:
441: for( i=1; i<=n; ++i ){
442: /* already in r0 */
443:
444: printf( " cmpl r0,$" );
445: printf( CONFMT, p[i].sval );
446: printf( "\n jeql L%d\n", p[i].slab );
447: }
448:
449: if( p->slab>=0 ) branch( p->slab );
450: }
451:
452: makeheap(p, m, n)
453: register struct sw *p;
454: {
455: register int q;
456:
457: q = select(m);
458: heapsw[n] = p[q];
459: if( q>1 ) makeheap(p, q-1, 2*n);
460: if( q<m ) makeheap(p+q, m-q, 2*n+1);
461: }
462:
463: select(m) {
464: register int l,i,k;
465:
466: for(i=1; ; i*=2)
467: if( (i-1) > m ) break;
468: l = ((k = i/2 - 1) + 1)/2;
469: return( l + (m-k < l ? m-k : l));
470: }
471:
472: walkheap(start, limit)
473: {
474: int label;
475:
476:
477: if( start > limit ) return;
478: printf(" cmpl r0,$%d\n", heapsw[start].sval);
479: printf(" jeql L%d\n", heapsw[start].slab);
480: if( (2*start) > limit ) {
481: printf(" jbr L%d\n", heapsw[0].slab);
482: return;
483: }
484: if( (2*start+1) <= limit ) {
485: label = getlab();
486: printf(" jgtr L%d\n", label);
487: } else
488: printf(" jgtr L%d\n", heapsw[0].slab);
489: walkheap( 2*start, limit);
490: if( (2*start+1) <= limit ) {
491: printf("L%d:\n", label);
492: walkheap( 2*start+1, limit);
493: }
494: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.