Bell 32V development
authorTom London <tbl@research.uucp>
Sun, 25 Mar 1979 10:35:56 +0000 (05:35 -0500)
committerTom London <tbl@research.uucp>
Sun, 25 Mar 1979 10:35:56 +0000 (05:35 -0500)
Work on file usr/src/cmd/pcc/code.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

usr/src/cmd/pcc/code.c [new file with mode: 0644]

diff --git a/usr/src/cmd/pcc/code.c b/usr/src/cmd/pcc/code.c
new file mode 100644 (file)
index 0000000..2d73d51
--- /dev/null
@@ -0,0 +1,417 @@
+# include "mfile1"
+#include <a.out.h>
+
+int proflg = 0;        /* are we generating profiling code? */
+int strftn = 0;  /* is the current function one which returns a value */
+int gdebug;
+int fdefflag;  /* are we within a function definition ? */
+char NULLNAME[8];
+int labelno;
+
+branch( n ){
+       /* output a branch to label n */
+       /* exception is an ordinary function branching to retlab: then, return */
+       if( n == retlab && !strftn ){
+               printf( "       ret\n" );
+               }
+       else printf( "  jbr     L%d\n", n );
+       }
+
+int lastloc = { -1 };
+
+short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
+#define LOG2SZ 9
+
+defalign(n) {
+       /* cause the alignment to become a multiple of n */
+       n /= SZCHAR;
+       if( lastloc != PROG && n > 1 ) printf( "        .align  %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
+       }
+
+locctr( l ){
+       register temp;
+       /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
+
+       if( l == lastloc ) return(l);
+       temp = lastloc;
+       lastloc = l;
+       switch( l ){
+
+       case PROG:
+               printf( "       .text\n" );
+               psline();
+               break;
+
+       case DATA:
+       case ADATA:
+               printf( "       .data\n" );
+               break;
+
+       case STRNG:
+               printf( "       .data   1\n" );
+               break;
+
+       case ISTRNG:
+               printf( "       .data   2\n" );
+               break;
+
+       case STAB:
+               printf( "       .stab\n" );
+               break;
+
+       default:
+               cerror( "illegal location counter" );
+               }
+
+       return( temp );
+       }
+
+deflab( n ){
+       /* output something to define the current position as label n */
+       printf( "L%d:\n", n );
+       }
+
+int crslab = 10;
+
+getlab(){
+       /* return a number usable for a label */
+       return( ++crslab );
+       }
+
+
+int ent_mask[] = {
+       0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
+
+int reg_use = 11;
+
+efcode(){
+       /* code for the end of a function */
+
+       if( strftn ){  /* copy output (in R2) to caller */
+               register NODE *l, *r;
+               register struct symtab *p;
+               register TWORD t;
+               register int j;
+               int i;
+
+               p = &stab[curftn];
+               t = p->stype;
+               t = DECREF(t);
+
+               deflab( retlab );
+
+               i = getlab();   /* label for return area */
+               printf("        .data\n" );
+               printf("        .align  2\n" );
+               printf("L%d:    .space  %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
+               printf("        .text\n" );
+               psline();
+               printf("        movab   L%d,r1\n", i);
+
+               reached = 1;
+               l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
+               l->rval = 1;  /* R1 */
+               l->lval = 0;  /* no offset */
+               r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
+               r->rval = 0;  /* R0 */
+               r->lval = 0;
+               l = buildtree( UNARY MUL, l, NIL );
+               r = buildtree( UNARY MUL, r, NIL );
+               l = buildtree( ASSIGN, l, r );
+               l->op = FREE;
+               ecomp( l->left );
+               printf( "       movab   L%d,r0\n", i );
+               /* turn off strftn flag, so return sequence will be generated */
+               strftn = 0;
+               }
+       branch( retlab );
+       printf( "       .set    .R%d,0x%x\n", ftnno, ent_mask[reg_use] );
+       reg_use = 11;
+       p2bend();
+       fdefflag = 0;
+       }
+
+bfcode( a, n ) int a[]; {
+       /* code for the beginning of a function; a is an array of
+               indices in stab for the arguments; n is the number */
+       register i;
+       register temp;
+       register struct symtab *p;
+       int off;
+       char *toreg();
+
+       locctr( PROG );
+       p = &stab[curftn];
+       printf( "       .align  1\n");
+       defnam( p );
+       temp = p->stype;
+       temp = DECREF(temp);
+       strftn = (temp==STRTY) || (temp==UNIONTY);
+
+       retlab = getlab();
+
+       /* routine prolog */
+
+       printf( "       .word   .R%d\n", ftnno);
+       if (gdebug) {
+               pstab(NULLNAME, N_SLINE);
+               printf("0,%d,LL%d\n", lineno, labelno);
+               printf("LL%d:\n", labelno++);
+       }
+       printf( "       subl2   $.F%d,sp\n", ftnno);
+       if( proflg ) {  /* profile code */
+               i = getlab();
+               printf("        movab   L%d,r0\n", i);
+               printf("        jsb     mcount\n");
+               printf("        .data\n");
+               printf("        .align  2\n");
+               printf("L%d:    .long   0\n", i);
+               printf("        .text\n");
+               psline();
+               }
+
+       off = ARGINIT;
+
+       for( i=0; i<n; ++i ){
+               p = &stab[a[i]];
+               if( p->sclass == REGISTER ){
+                       temp = p->offset;  /* save register number */
+                       p->sclass = PARAM;  /* forget that it is a register */
+                       p->offset = NOOFFSET;
+                       oalloc( p, &off );
+/*tbl*/                printf( "       %s      %d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
+                       p->offset = temp;  /* remember register number */
+                       p->sclass = REGISTER;   /* remember that it is a register */
+                       }
+               else {
+                       if( oalloc( p, &off ) ) cerror( "bad argument" );
+                       }
+
+               }
+       fdefflag = 1;
+       }
+
+bccode(){ /* called just before the first executable statment */
+               /* by now, the automatics and register variables are allocated */
+       SETOFF( autooff, SZINT );
+       /* set aside store area offset */
+       p2bbeg( autooff, regvar );
+       reg_use = (reg_use > regvar ? regvar : reg_use);
+       }
+
+ejobcode( flag ){
+       /* called just before final exit */
+       /* flag is 1 if errors, 0 if none */
+       }
+
+aobeg(){
+       /* called before removing automatics from stab */
+       }
+
+aocode(p) struct symtab *p; {
+       /* called when automatic p removed from stab */
+       }
+
+aoend(){
+       /* called after removing all automatics from stab */
+       }
+
+defnam( p ) register struct symtab *p; {
+       /* define the current location as the name p->sname */
+
+       if( p->sclass == EXTDEF ){
+               printf( "       .globl  %s\n", exname( p->sname ) );
+               }
+       if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
+       else printf( "%s:\n", exname( p->sname ) );
+
+       }
+
+bycode( t, i ){
+       /* put byte i+1 in a string */
+
+       i &= 07;
+       if( t < 0 ){ /* end of the string */
+               if( i != 0 ) printf( "\n" );
+               }
+
+       else { /* stash byte t into string */
+               if( i == 0 ) printf( "  .byte   " );
+               else printf( "," );
+               printf( "0x%x", t );
+               if( i == 07 ) printf( "\n" );
+               }
+       }
+
+zecode( n ){
+       /* n integer words of zeros */
+       OFFSZ temp;
+       if( n <= 0 ) return;
+       printf( "       .space  %d\n", (SZINT/SZCHAR)*n );
+       temp = n;
+       inoff += temp*SZINT;
+       }
+
+fldal( t ) unsigned t; { /* return the alignment of field of type t */
+       uerror( "illegal field type" );
+       return( ALINT );
+       }
+
+fldty( p ) struct symtab *p; { /* fix up type of field p */
+       ;
+       }
+
+where(c){ /* print location of error  */
+       /* c is either 'u', 'c', or 'w' */
+       /* GCOS version */
+       fprintf( stderr, "%s, line %d: ", ftitle, lineno );
+       }
+
+
+/* tbl - toreg() returns a pointer to a char string
+                 which is the correct  "register move" for the passed type 
+ */
+struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
+       {
+       CHAR, "cvtbl",
+       SHORT, "cvtwl",
+       INT, "movl",
+       LONG, "movl",
+       FLOAT, "movf",
+       DOUBLE, "movd",
+       UCHAR,  "movzbl",
+       USHORT, "movzwl",
+       UNSIGNED,       "movl",
+       ULONG,  "movl",
+       -1, ""
+       };
+
+char
+*toreg(type)
+       TWORD type;
+{
+       struct type_move *p;
+
+       for ( p=toreg_strs; p->fromtype > 0; p++)
+               if (p->fromtype == type) return(p->tostrng);
+
+       /* type not found, must be a pointer type */
+       return("movl");
+}
+/* tbl */
+
+
+main( argc, argv ) char *argv[]; {
+       return(mainp1( argc, argv ));
+       }
+
+struct sw heapsw[SWITSZ];      /* heap for switches */
+
+genswitch(p,n) register struct sw *p;{
+       /*      p points to an array of structures, each consisting
+               of a constant value and a label.
+               The first is >=0 if there is a default label;
+               its value is the label number
+               The entries p[1] to p[n] are the nontrivial cases
+               */
+       register i;
+       register CONSZ j, range;
+       register dlab, swlab;
+
+       range = p[n].sval-p[1].sval;
+
+       if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
+
+               swlab = getlab();
+               dlab = p->slab >= 0 ? p->slab : getlab();
+
+               /* already in r0 */
+               printf("        casel   r0,$%ld,$%ld\n", p[1].sval, range);
+               printf("L%d:\n", swlab);
+               for( i=1,j=p[1].sval; i<=n; j++) {
+                       printf("        .word   L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
+                               swlab);
+                       }
+
+               if( p->slab >= 0 ) branch( dlab );
+               else printf("L%d:\n", dlab);
+               return;
+
+               }
+
+       if( n>8 ) {     /* heap switch */
+
+               heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
+               makeheap(p, n, 1);      /* build heap */
+
+               walkheap(1, n); /* produce code */
+
+               if( p->slab >= 0 )
+                       branch( dlab );
+               else
+                       printf("L%d:\n", dlab);
+               return;
+       }
+
+       /* debugging code */
+
+       /* out for the moment
+       if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
+       */
+
+       /* simple switch code */
+
+       for( i=1; i<=n; ++i ){
+               /* already in r0 */
+
+               printf( "       cmpl    r0,$" );
+               printf( CONFMT, p[i].sval );
+               printf( "\n     jeql    L%d\n", p[i].slab );
+               }
+
+       if( p->slab>=0 ) branch( p->slab );
+       }
+
+makeheap(p, m, n)
+register struct sw *p;
+{
+       register int q;
+
+       q = select(m);
+       heapsw[n] = p[q];
+       if( q>1 ) makeheap(p, q-1, 2*n);
+       if( q<m ) makeheap(p+q, m-q, 2*n+1);
+}
+
+select(m) {
+       register int l,i,k;
+
+       for(i=1; ; i*=2)
+               if( (i-1) > m ) break;
+       l = ((k = i/2 - 1) + 1)/2;
+       return( l + (m-k < l ? m-k : l));
+}
+
+walkheap(start, limit)
+{
+       int label;
+
+
+       if( start > limit ) return;
+       printf("        cmpl    r0,$%d\n",  heapsw[start].sval);
+       printf("        jeql    L%d\n", heapsw[start].slab);
+       if( (2*start) > limit ) {
+               printf("        jbr     L%d\n", heapsw[0].slab);
+               return;
+       }
+       if( (2*start+1) <= limit ) {
+               label = getlab();
+               printf("        jgtr    L%d\n", label);
+       } else
+               printf("        jgtr    L%d\n", heapsw[0].slab);
+       walkheap( 2*start, limit);
+       if( (2*start+1) <= limit ) {
+               printf("L%d:\n", label);
+               walkheap( 2*start+1, limit);
+       }
+}