3 /*#include "config.h" manifest.h*/
4 /*#include "macdefs.h" manifest.h*/
5 /*#include "manifest.h" pass1.h*/
6 /*#include "ndu.h" manifest.h*/
8 /*#include "pcclocal.h" macdefs.h*/
10 #if defined(DOSCCS) && !defined(lint)
11 static char *sccsid ="@(#)code.c 1.5 (Berkeley) 8/23/85";
14 /*# include "pass1.h"*/
15 /*# include <sys/types.h>*/
16 /*# include <a.out.h>*/
17 /*# include <stab.h>*/
19 int proflg = 0; /* are we generating profiling code? */
20 int strftn = 0; /* is the current function one which returns a value */
22 int fdefflag; /* are we within a function definition ? */
26 # define putstr(s) fputs((s), stdout)
28 int branch(n) int n; {
29 /* output a branch to label n */
30 /* exception is an ordinary function branching to retlab: then, return */
31 if( n == retlab && !strftn ){
34 else printf( " jbr L%d\n", n );
39 short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
42 int defalign(n) int n; {
43 /* cause the alignment to become a multiple of n */
45 if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
48 int locctr(l) int l; {
50 /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
52 if( l == lastloc ) return(l);
68 putstr( " .data 1\n" );
72 putstr( " .data 2\n" );
80 cerror( "illegal location counter" );
86 int deflab(n) int n; {
87 /* output something to define the current position as label n */
88 printf( "L%d:\n", n );
94 /* return a number usable for a label */
99 0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
104 /* code for the end of a function */
106 if( strftn ){ /* copy output (in R2) to caller */
107 register NODE *l, *r;
108 register struct symtab *p;
118 i = getlab(); /* label for return area */
121 putstr(" .align 2\n" );
122 printf("L%d: .space %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
125 { int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR;
126 if (sz % sizeof (int))
127 sz += sizeof (int) - (sz % sizeof (int));
128 printf(" .lcomm L%d,%d\n", i, sz);
132 printf(" movab L%d,r1\n", i);
135 l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
136 l->tn.rval = 1; /* R1 */
137 l->tn.lval = 0; /* no offset */
138 r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
139 r->tn.rval = 0; /* R0 */
141 l = buildtree( UNARY MUL, l, NIL );
142 r = buildtree( UNARY MUL, r, NIL );
143 l = buildtree( ASSIGN, l, r );
146 printf( " movab L%d,r0\n", i );
147 /* turn off strftn flag, so return sequence will be generated */
152 printf( " .set L%d,0x%x\n", ftnno, ent_mask[reg_use] );
154 printf( " .set L%d,%d # Hex = 0x%x\n", ftnno, 0x3c| ent_mask[reg_use], ent_mask[reg_use] );
155 /* KLS kludge, under VMS if you use regs 2-5, you must save them. */
164 int bfcode(a, n) int a[]; int n; {
165 /* code for the beginning of a function; a is an array of
166 indices in stab for the arguments; n is the number */
169 register struct symtab *p;
175 putstr( " .align 1\n");
179 strftn = (temp==STRTY) || (temp==UNIONTY);
185 printf( " .word L%d\n", ftnno);
188 printf( " jbr L%d\n", ftlab1);
189 printf( "L%d:\n", ftlab2);
190 if( proflg ) { /* profile code */
192 printf(" movab L%d,r0\n", i);
193 putstr(" jsb mcount\n");
195 putstr(" .align 2\n");
196 printf("L%d: .long 0\n", i);
203 for( i=0; i<n; ++i ){
205 if( p->sclass == REGISTER ){
206 temp = p->offset; /* save register number */
207 p->sclass = PARAM; /* forget that it is a register */
208 p->offset = NOOFFSET;
210 /*tbl*/ printf( " %s %d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
211 p->offset = temp; /* remember register number */
212 p->sclass = REGISTER; /* remember that it is a register */
214 else if( p->stype == STRTY || p->stype == UNIONTY ) {
215 p->offset = NOOFFSET;
216 if( oalloc( p, &off ) ) cerror( "bad argument" );
217 SETOFF( off, ALSTACK );
220 if( oalloc( p, &off ) ) cerror( "bad argument" );
226 pstabdot(N_SLINE, lineno);
228 pstab(NULLNAME, N_SLINE);
229 printf("0,%d,LL%d\n", lineno, labelno);
230 printf("LL%d:\n", labelno++);
236 int bccode() { /* called just before the first executable statment */
237 /* by now, the automatics and register variables are allocated */
238 SETOFF( autooff, SZINT );
239 /* set aside store area offset */
240 p2bbeg( autooff, regvar );
241 reg_use = (reg_use > regvar ? regvar : reg_use);
244 int ejobcode(flag) int flag; {
245 /* called just before final exit */
246 /* flag is 1 if errors, 0 if none */
250 /* called before removing automatics from stab */
253 int aocode(p) struct symtab *p; {
254 /* called when automatic p removed from stab */
258 /* called after removing all automatics from stab */
261 int defnam(p) register struct symtab *p; {
262 /* define the current location as the name p->sname */
264 if( p->sclass == EXTDEF ){
265 printf( " .globl %s\n", exname( p->sname ) );
267 if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
268 else printf( "%s:\n", exname( p->sname ) );
272 int bycode(t, i) int t; int i; {
274 static int lastoctal = 0;
277 /* put byte i+1 in a string */
283 if ( i != 0 ) putstr( "\"\n" );
285 if ( i == 0 ) putstr("\t.ascii\t\"");
286 if ( t == '\\' || t == '"'){
291 * We escape the colon in strings so that
292 * c2 will, in its infinite wisdom, interpret
293 * the characters preceding the colon as a label.
294 * If we didn't escape the colon, c2 would
295 * throw away any trailing blanks or tabs after
296 * the colon, but reconstruct a assembly
297 * language semantically correct program.
298 * C2 hasn't been taught about strings.
300 else if ( t == ':' || t < 040 || t >= 0177 ){
304 else if ( lastoctal && '0' <= t && t <= '9' ){
306 printf("\"\n\t.ascii\t\"%c", t );
312 if ( i == 077 ) putstr("\"\n");
317 if( t < 0 ){ /* end of the string */
318 if( i != 0 ) putchar( '\n' );
321 else { /* stash byte t into string */
322 if( i == 0 ) putstr( " .byte " );
325 if( i == 07 ) putchar( '\n' );
330 int zecode(n) int n; {
331 /* n integer words of zeros */
334 printf( " .space %d\n", (SZINT/SZCHAR)*n );
339 int fldal(t) unsigned t; { /* return the alignment of field of type t */
340 uerror( "illegal field type" );
344 int fldty(p) struct symtab *p; { /* fix up type of field p */
348 int where(c) int c; { /* print location of error */
349 /* c is either 'u', 'c', or 'w' */
351 fprintf( stderr, "%s, line %d: ", ftitle, lineno );
354 /* tbl - toreg() returns a pointer to a char string
355 which is the correct "register move" for the passed type
357 struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] = {
371 char *toreg(type) TWORD type; {
374 for ( p=toreg_strs; p->fromtype != 0; p++)
375 if (p->fromtype == type) return(p->tostrng);
377 /* type not found, must be a pointer type */
382 int main(argc, argv) int argc; char *argv[]; {
385 setbuf(stderr, errbuf);
387 return(mainp1( argc, argv ));
390 struct sw heapsw[SWITSZ]; /* heap for switches */
392 int genswitch(p, n) register struct sw *p; int n; {
393 /* p points to an array of structures, each consisting
394 of a constant value and a label.
395 The first is >=0 if there is a default label;
396 its value is the label number
397 The entries p[1] to p[n] are the nontrivial cases
400 register CONSZ j, range;
401 register dlab, swlab;
403 range = p[n].sval-p[1].sval;
405 if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
408 dlab = p->slab >= 0 ? p->slab : getlab();
411 printf(" casel r0,$%ld,$%ld\n", p[1].sval, range);
412 printf("L%d:\n", swlab);
413 for( i=1,j=p[1].sval; i<=n; j++) {
414 printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
418 if( p->slab >= 0 ) branch( dlab );
419 else printf("L%d:\n", dlab);
424 if( n>8 ) { /* heap switch */
426 heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
427 makeheap(p, n, 1); /* build heap */
429 walkheap(1, n); /* produce code */
434 printf("L%d:\n", dlab);
440 /* out for the moment
441 if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
444 /* simple switch code */
446 for( i=1; i<=n; ++i ){
449 putstr( " cmpl r0,$" );
450 printf( CONFMT, p[i].sval );
451 printf( "\n jeql L%d\n", p[i].slab );
454 if( p->slab>=0 ) branch( p->slab );
457 int makeheap(p, m, n) register struct sw *p; int m; int n; {
462 if( q>1 ) makeheap(p, q-1, 2*n);
463 if( q<m ) makeheap(p+q, m-q, 2*n+1);
466 int select(m) int m; {
470 if( (i-1) > m ) break;
471 l = ((k = i/2 - 1) + 1)/2;
472 return( l + (m-k < l ? m-k : l));
475 int walkheap(start, limit) int start; int limit; {
478 if( start > limit ) return;
479 printf(" cmpl r0,$%d\n", heapsw[start].sval);
480 printf(" jeql L%d\n", heapsw[start].slab);
481 if( (2*start) > limit ) {
482 printf(" jbr L%d\n", heapsw[0].slab);
485 if( (2*start+1) <= limit ) {
487 printf(" jgtr L%d\n", label);
489 printf(" jgtr L%d\n", heapsw[0].slab);
490 walkheap( 2*start, limit);
491 if( (2*start+1) <= limit ) {
492 printf("L%d:\n", label);
493 walkheap( 2*start+1, limit);