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