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