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