diff --git a/WEGA/contrib/lcc/cmd/comp/u8k/debug.c b/WEGA/contrib/lcc/cmd/comp/u8k/debug.c new file mode 100644 index 0000000..0318f8c --- /dev/null +++ b/WEGA/contrib/lcc/cmd/comp/u8k/debug.c @@ -0,0 +1,584 @@ +/* debug.c -- symbol table output routines for common assembler */ + +#include +#include "mfile1.h" +#include "macdefs.h" +#include + +static FILE * outfile = stdout; /* static now, maybe global later */ + +#define LINENO (lineno-startln+1) /* local line number */ + +static int startln; /* editor line number of opening { */ +static int oldln; /* last line number printed */ +int gdebug; /* -g flag */ +static char startfn[100]; /* file name of the opening { */ +static char fncname[BUFSIZ+1]; /* name of current function */ +static int bb_flags[BCSZ]; /* remember whether or not bb + ** is needed + */ + +fixdef(p) struct symtab *p; { + + /* print debugging info + * + * don't do params, externs, structure names or members + * at this time; they are delayed until more information + * is known about them + */ + + switch( p->sclass ) { + + case USTATIC: + case EXTERN: + case EXTDEF: + case STNAME: + case UNAME: + case ENAME: + case MOS: + case MOE: + case MOU: + return; + default: + if( p->sclass & FIELD ) return; + } + + /* parameters */ + if( p->slevel == 1 ) return; + + /* static externs */ + if( p->sclass == STATIC && p->slevel == 0 ) return; + + prdef(p,0); + } + +prdims( p ) struct symtab *p; { + /* print debugging info for dimensions + */ + int temp, dtemp, dflag; + OFFSZ tsize(); + + dflag = 0; /* need to print dim */ + dtemp = p->dimoff; + + for( temp=p->stype; temp&TMASK; temp = DECREF(temp) ) { + /* put out a dimension for each instance of ARY in type word */ + + if( ISARY(temp) ) { + if( !dflag ) { + fprintf( outfile, " dim %ld", dimtab[dtemp++] ); + dflag = 1; + } + else + fprintf( outfile, ",%ld", dimtab[dtemp++] ); + } + } + + if( dflag ) { + fputs( ";\tsize\t", outfile ); + fprintf( outfile, /*CONFMT*/"%ld", tsize(p->stype, p->dimoff, p->sizoff ) / SZCHAR ); + putc( ';', outfile ); + } + } + +/* local table of fakes for un-names structures + * sizoff for ~ifake is stored in mystrtab[i] + */ +#define FAKENM 99 /* maximum number of fakenames */ +int mystrtab[FAKENM], ifake = 0; +struct symtab mytable; + char tagname[BUFSIZ] = ""; + +prdef(p,dsflg) struct symtab *p; int dsflg; { + /* print symbol definition pseudos + */ + TWORD pty, bpty; + TWORD chgtype(); + char *strname(); + int sclass; + int saveloc; + + if ( dsflg || !gdebug ) + return; + + /* translate storage class */ + + switch( p->sclass ){ + case AUTO: sclass = C_AUTO; break; + case EXTDEF: + case EXTERN: sclass = C_EXT; break; + case STATIC: sclass = C_STAT; break; + case REGISTER: sclass = blevel==1 ? C_REGPARM : C_REG; break; + case ULABEL: + case LABEL: sclass = C_LABEL; break; + case MOS: sclass = C_MOS; break; + case PARAM: sclass = C_ARG; break; + case STNAME: sclass = C_STRTAG; break; + case MOU: sclass = C_MOU; break; + case UNAME: sclass = C_UNTAG; break; + case TYPEDEF: sclass = C_TPDEF; break; + case ENAME: sclass = C_ENTAG; break; + case MOE: sclass = C_MOE; break; + default: if( p->sclass & FIELD ) + sclass = C_FIELD; + else + cerror( "bad storage class %d", p->sclass ); + break; + } + + /* print a bb symbol if this is the first symbol in the block */ + + if( blevel > 2 && !bb_flags[blevel] && sclass != C_LABEL ) { + fprintf( outfile, " def ~bb; val ~; scl %d; line %d; endef\n", C_BLOCK, LINENO ); + bb_flags[blevel] = 1; /* don't let another bb print */ + } + + /* make sure that defs in functions are in text section */ + if( blevel > 1 ) + saveloc = locctr( PROG ); + + fprintf( outfile, " def %s;", exname( p->sname ) ); + + switch( sclass ) { /* print val based on storage class */ + + case C_AUTO: + /* offset in bytes plus savearea */ + fprintf( outfile, " val %ld+S%%%d;", + p->offset/SZCHAR, ftnno ); + break; + + case C_MOS: + case C_MOU: + case C_ARG: + /* offset in bytes */ + fprintf( outfile, " val %ld;", p->offset/SZCHAR ); + break; + + case C_FIELD: + case C_MOE: + /* offset in bits, or internal value of enum symbol */ + fprintf( outfile, " val %ld;", p->offset ); + break; + + case C_REGPARM: + case C_REG: + /* offset in bytes in savearea for reg vars */ + /* actual offset determination is deferred to the asembler */ + /* pointer vars in %aN indicated by adding 8 */ + fprintf( outfile, " val %ld;", OUTREGNO(p)); + break; + + case C_STAT: + case C_LABEL: + case C_EXT: + /* actual or hidden name, depending on scope */ + if( p->slevel != 0 ) + { + fprintf( outfile, " val "); + fprintf( outfile, LABFMT, (int)p->offset ); + putc( ';', outfile); + } + else + fprintf( outfile, " val %s;", + exname( p->sname ) ); + break; + + default: + break; + } + + pty = chgtype(p->stype); /* change type word from new style + ** to old + */ + bpty = BTYPE(p->stype); + fprintf( outfile, " scl %d; type 0%o;", sclass, pty ); + + /* print tag and size info, size only for tags themselves; + * don't print if size not known + */ + + if (dimtab[p->sizoff] > 0) + switch( sclass ) { + + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + fprintf( outfile, " size %ld;", dimtab[p->sizoff] / SZCHAR ); + break; + + default: /* bpty is base type */ + if( (bpty == STRTY || bpty == UNIONTY || bpty == ENUMTY) && gdebug ) { + char buf[BUFSIZ]; + + (void) strcpy( buf, strname( p->sizoff ) ); + if ( buf[0] == '$' ) + buf[0] = '_'; + fprintf( outfile, " tag %s;", + exname( buf ) ); + fprintf( outfile, " size %ld;", + dimtab[p->sizoff] / SZCHAR ); + } + break; + } + +#ifdef FOOBARBLETCH + /* print line for block symbols */ + + if( p->slevel > 2 ) + fprintf( outfile, " line %d;", LINENO ); +#endif FOOBARBLETCH + + /* look for dimensions to print */ + + if( sclass != C_LABEL && gdebug ) + prdims( p ); + + /* size of field is its length in bits */ + + if( sclass == C_FIELD ) + fprintf( outfile, " size %d;", p->sclass & FLDSIZ ); + + fputs( "\tendef\n", outfile ); + if( blevel > 1 ) + locctr( saveloc ); + } + +strend( dimst ) int dimst; { + /* called at the end of a structure declaration + * this routine puts out the structure tag, its members + * and an eos. dimst is the index in dimtab of the + * structure description + */ + int member; + OFFSZ size; + int saveloc; + struct symtab *memptr, *tagnm, *strfind(); + + if( !gdebug ) return; + + /* set locctr to text */ + saveloc = locctr( PROG ); + + /* set up tagname */ + member = dimtab[dimst + 1]; + tagnm = strfind(dimst); + + if( tagnm == NULL ) { + /* create a fake if there is no tagname */ + /* use the local symbol table */ + tagnm = &mytable; + if( ifake == FAKENM ) + cerror( "fakename table overflow" ); + + /* generate the fake name and enter into the fake table */ + { + char buf[BUFSIZ]; + + sprintf( buf, "~%dfake", ifake ); + mytable.sname = savestr( buf ); /* lives forever! */ + } + mystrtab[ifake++] = dimst; + memptr = &stab[dimtab[member]]; + + /* fix up the fake's class, type, and sizoff based on class of its members */ + switch( memptr->sclass ) { + case MOS: + tagnm->sclass = STNAME; + tagnm->stype = STRTY; + break; + case MOE: + tagnm->sclass = ENAME; + tagnm->stype = ENUMTY; + break; + case MOU: + tagnm->sclass = UNAME; + tagnm->stype = UNIONTY; + break; + default: + if( memptr->sclass & FIELD ){ + tagnm->sclass = STNAME; + tagnm->stype = STRTY; + } + else + cerror( "can't identify type of fake tagname" ); + } + tagnm->slevel = 0;; + tagnm->sizoff = dimst; + } + + /* print out the structure header */ + { + char buf[BUFSIZ], *saveit; + + saveit = tagnm->sname; + (void) strncpy( buf, saveit, BUFSIZ - 1 ); + buf[BUFSIZ - 1] = '\0'; + tagnm->sname = buf; + if ( buf[0] == '$' ) + buf[0] = '_'; + prdef( tagnm, 0 ); + tagnm->sname = saveit; + } + + /* print out members */ + while( dimtab[member] >= 0 ) { + memptr = &stab[dimtab[member++]]; + { + char buf[BUFSIZ], *saveit; + + saveit = memptr->sname; + (void) strncpy( buf, saveit, BUFSIZ - 1 ); + buf[BUFSIZ - 1] = '\0'; + memptr->sname = buf; + if ( buf[0] == '$' ) + buf[0] = '_'; + prdef( memptr, 0 ); + memptr->sname = saveit; + } + } + + /* print eos */ + size = dimtab[dimst] / SZCHAR; + fprintf( outfile, " def ~eos; val %ld; scl %d;", size, C_EOS ); + fprintf( outfile, " tag %s; size %ld; endef\n", + exname( tagnm->sname ), size ); + + /* return to old locctr */ + locctr( saveloc ); + } + +struct symtab * +strfind( key ) int key; { + /* find the structure tag in the symbol table, 0 == not found + */ + struct symtab *sptr; + char spc; + for( sptr = stab; sptr < stab + SYMTSZ; ++sptr ) { + spc = sptr->sclass; + if( (spc == STNAME || spc == ENAME || spc == UNAME ) && sptr->sizoff == key && sptr->stype != TNULL ) + return( sptr ); + } + /* not found */ + return( NULL ); + } + +char * +strname( key ) int key; { + /* return a pointer to the tagname, + * the fake table is used if not found by strfind + */ + int i; + struct symtab *tagnm, *strfind(); + tagnm = strfind( key ); + if( tagnm != NULL ) + return( tagnm->sname ); + + for( i = 0; i < FAKENM; ++i ) + if( mystrtab[i] == key ) { + sprintf( tagname, "~%dfake", i ); + return( tagname ); + } + + cerror( "structure tagname not found" ); + return(NULL); + } + +/* chgtype -- change type word from pcc2 internal type to +** old style type for symbol table utilities. +** +** The old and new types are sufficiently similar to obtain the +** old from the new by extracting the basic type, shifting the +** remaining bits right 1, then OR-ing them back with the basic +** type. That will probably not continue to be true. +*/ + +/* Define old types */ + +#define O_TNULL 020 +#define O_TVOID 040 +#define O_UNDEF 00 +#define O_FARG 01 +#define O_CHAR 02 +#define O_SHORT 03 +#define O_INT 04 +#define O_LONG 05 +#define O_FLOAT 06 +#define O_DOUBLE 07 +#define O_STRTY 010 +#define O_UNIONTY 011 +#define O_ENUMTY 012 +#define O_MOETY 013 +#define O_UCHAR 014 +#define O_USHORT 015 +#define O_UNSIGNED 016 +#define O_ULONG 017 + +TWORD +chgtype(ntype) +TWORD ntype; /* new type */ +{ + TWORD btype = BTYPE(ntype); /* get basic type */ + TWORD other = ntype & ~((TWORD) BTMASK); + /* get remaining bits */ + + TWORD newtype; /* derived "new" (i.e., old-style) type */ + + switch ( btype ) /* convert basic type */ + { + case TNULL: newtype = O_TNULL; break; + case FARG: newtype = O_FARG; break; + case CHAR: newtype = O_CHAR; break; + case SHORT: newtype = O_SHORT; break; + case INT: newtype = O_INT; break; + case LONG: newtype = O_LONG; break; + case FLOAT: newtype = O_FLOAT; break; + case DOUBLE: newtype = O_DOUBLE; break; + case STRTY: newtype = O_STRTY; break; + case UNIONTY: newtype = O_UNIONTY; break; + case ENUMTY: newtype = O_ENUMTY; break; + case MOETY: newtype = O_MOETY; break; + case UCHAR: newtype = O_UCHAR; break; + case USHORT: newtype = O_USHORT; break; + case UNSIGNED: newtype = O_UNSIGNED; break; + case ULONG: newtype = O_ULONG; break; + case VOID: newtype = O_TVOID; break; + case UNDEF: newtype = O_UNDEF; break; + default: cerror("Unknown basic type\n"); + } + return( (other >> 1) | newtype ); /* return changed type */ +} + + +beg_file(){ + /* called as the very first thing by the parser to do machine + * dependent stuff + */ + register char * p; + register char * s; + extern fpe_catch(); + + /* note: double quotes already in ftitle... */ + p = ftitle + strlen( ftitle ) - 2; + *(p+1) = '\"'; + s = p - 14; /* max name length */ + while ( p > s && *p != '"' && *p != '/' ) + --p; + fprintf( outfile, ".line 1 \"%.15s\n", p + 1 ); + fprintf( outfile, "\t.seg\n\tfp := r13\n\tFP := rr12\n"); + fprintf( outfile, "\tsp := r15\n\tSP := rr14\n"); + + /* + * Catch floating exceptions generated by the constant + * folding code. + */ + (void) signal( SIGFPE, fpe_catch ); +} + +fpe_catch() { + /* + * Floating exception generated by constant folding. + */ + /* "floating point constant folding causes exception" */ + uerror( "floating point constant folding causes exception" ); + exit(2); + } + +sdbline() +{ + if ( gdebug && lineno != oldln ) + { + oldln = lineno; /* remember last line no. output */ + if ( curloc == PROG && strcmp( startfn, ftitle ) == 0 ) + fprintf( outfile, " ln %d\n", LINENO ); + } + return; +} + + +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 + * print eb here if bb printed for this block + */ +# ifndef NOSYMB + if( gdebug && bb_flags[blevel+1] ) { + fprintf( outfile, " def ~eb; val ~; scl %d; line %d; endef\n", C_BLOCK, LINENO ); + bb_flags[blevel+1] = 0; + } +# endif + } + + +bfdebug( a, n ) +int a[]; +int n; +{ + register i; + register struct symtab *p; + + /* remember name of current function */ + + (void) strcpy( fncname, stab[curftn].sname ); + + /* initialize line number counters */ + + oldln = startln = lineno; + strcpy( startfn, ftitle ); + + /* do ~bf symbol and defs for parameters + * parameters are delayed to here to two reasons: + * 1: they appear inside the ~bf - ~ef + * 2: the true declarations have been seen + */ + if ( gdebug ) { + int line; + + fprintf( outfile, " ln 1\n"); + line = lineno; /* line number information for sdb */ + fprintf( outfile, " def ~bf; val ~; scl %d; line %d; endef\n", C_FCN ,line ); + for( i=0; i 1 ) + fprintf( outfile, " ln %d\n", LINENO ); + } +} + +eobl2dbg() +{ + /* print debug information at lexical end of function */ + + if ( gdebug ) + { + fprintf( outfile, "\tdef %s; val ~; scl -1; endef\n", fncname); + } + return; +} + + +/* called at end of job to output debug information */ +ejsdb() +{ +} diff --git a/WEGA/contrib/lcc/cmd/comp/u8k/local.c b/WEGA/contrib/lcc/cmd/comp/u8k/local.c new file mode 100644 index 0000000..4073fbd --- /dev/null +++ b/WEGA/contrib/lcc/cmd/comp/u8k/local.c @@ -0,0 +1,760 @@ +# include "mfile1.h" +#include + +/* the following used to be on the old local.c file */ +/* the register variables are %d2 through %d7 and %a2 through %a5 */ +/* everything is saved on the stack as a 4 byte quantity */ +/* the machine-independent part maintains a quantity regvar that is */ +/* saved and restored across block boundaries */ +/* if cisreg likes the type, it calls rallc to get a register number */ +/* rallc puts the register number into nextrvar, and updates regvar */ +/* rallc returns 0 if there are no free regs of that type, else 1 */ + +#define EXPSHIFT 7 +#define EXPMASK (0xff << EXPSHIFT) /* mask to access exponent on VAX */ +#define EXPLORD ( 1L << EXPSHIFT ) /* low order exponent bit on VAX */ +#define SIGNMASK ( 1L << 15 ) /* Vax sign bit */ + +/* Berechnen der Datensegmente */ + +char datanm[8] = "data "; +static unsigned short datasiz[32]; +xxx(i) +register unsigned i; +{ + register int j; + register long l; + + for (j = 0; j < 32; j++) + { + l = datasiz[j]; + l += i; + if ( l >= 0xfff8l ) + continue; + datasiz[j] = l; + if (j) + sprintf(datanm, "modul%d", j+3); + else + strcpy(datanm, "data"); + return(0); + } + uerror( "data segments exhausted"); +} + +fincode( d, sz ) +double d; +{ + /* initialization of floats */ + union { + float f; + double d; + struct { long l,l2; } lg; + struct { short slo, shi; } sh; + } x; + long z; + register long exponent,fract1,fract2,sign; + +#ifndef ONEFLOAT + if ( sz == SZDOUBLE ) + { + x.d = d; + printf(" .long %%%lx\t// %e \n", x.lg.l, d ); + printf(" .long %%%lx\n", x.lg.l2); + } + else +#endif + { + x.f = d; + printf(" .long %%%lx\t// %e */\n", x.lg.l, d ); + } + inoff += sz; +} + +rallc( t ) +register TWORD t; +{ + register int i; + if ( ISPTR(t) || t == LONG || t == ULONG) + { + if (regvar & 0xc00) + { + if (regvar & 0x300) + return(0); + else + { + regvar |= 0x300; + nextrvar = 8; + } + } + else + { + regvar |= 0xc00; + nextrvar = 10; + } + return(1); + } + else + { + for (i = 11; i >= 8; i--) + { + if (regvar & (1<in.left->tn.op != ICON ) yyerror( "illegal initializer" ); + t = p->tn.type; + q = p->in.left; + inoff += sz; + if( q->tn.rval != NONAME ) /* do real pointers in pass 2 */ + { + ecode( p ); + return; + } + +/* NOTE: assembler will complain about constants that are too big +** for the type of item that is being initialized (like "byte 0x1000"). +** The compiler should produce a message about this some day. +*/ + + switch( (int)t ) + { + case CHAR: + case UCHAR: + printf( "\t.byte\t%%%lx\n", q->tn.lval ); + return; + + case INT: + case UNSIGNED: + printf( "\t.word\t%%%x\n",(unsigned short) (q->tn.lval) ); + return; + + default: + if( !ISPTR(t) ) + werror( "initialization error probable"); + /* FALLTHRU */ + + case LONG: + case ULONG: + printf( "\t.long\t%%%lx\n", q->tn.lval ); + return; + } +} + +cisreg( t ) +register TWORD t; +{ + /* is an automatic variable of type t OK for a register variable */ + + switch( t ) + { + default: + if( !ISPTR(t) ) return( 0 ); + /* FALLTHRU */ + case SHORT: + case USHORT: + case INT: + case UNSIGNED: + case LONG: + case ULONG: +/* + case CHAR: + case UCHAR: + case FLOAT: +no characters and floats in registers (of) */ +#ifdef ONEFLOAT + case DOUBLE: +#endif + return(rallc(t)); + } +} + +static int inwd; /* current bit offset in word */ +static long word; /* word being built from fields */ + +incode( p, sz ) +register NODE *p; +{ + register long v; + + /* generate initialization code for assigning a constant c + ** to a field of width sz + */ + /* we assume that the proper alignment has been obtained */ + /* inoff is updated to have the proper final value */ + /* go to some pain to handle the left-to-right fields, and defend + /* against possible long bitfield initialization */ + /* ordinary (int sized) fields are + /* left to right for the 68000 */ + + v = p->tn.lval & ((1<>SZSHORT)); + else +/* printf( " long 0x%.8lx\n", word); */ + printf( "\t.long\t%%%.8lx\n", word ); + word = inwd = 0; + } +} + +vfdzero( n ) +register n; +{ + /* define n bits of zeros in a vfd */ + + if( n <= 0 ) return; + inwd += n; + inoff += n; + if( inoff%ALSHORT == 0 ) + { + if( inwd == SZSHORT ) + printf( "\t.word\t%%%.4x\n", + (unsigned short)(word>>SZSHORT)); + else + printf( "\t.long\t%%%.8lx\n", word); + word = inwd = 0; + } +} + +char * +exname( p ) +char *p; +{ + return( p ); +} + +commdec( id ) +{ + /* make a common declaration for id, if reasonable */ + register struct symtab *q; + register OFFSZ sz; + + q = &stab[id]; + sz = tsize( q->stype, q->dimoff, q->sizoff )/SZCHAR; + if (sz < 0) + { + int val; + + val = sz; + if (val == sz) + { + if (nerrors) + nerrors--; + sz = (unsigned)val; + } + } + +# ifndef NOSYMB + if ( q->slevel == 0) + prdef(q, 0); /* output debug info */ +# endif + if( q->sclass==STATIC ) + { + xxx((int)sz); + if( q->slevel ) + printf("\t.psec\t%s\n\t.data\n\t.even\nL%d:\n", + datanm,(int)(q->offset) ); + else + printf( "\t.even\n_%s:\n", exname( q->sname ) ); + printf( "\t.=.+%ld\n", (sz%2)? sz+1: sz); + if( q->slevel ) + printf( "\t.psec\n\t.code\n" ); + } + else { + printf( "\t.comm\t%ld,\t_%s;\n", sz, exname( q->sname) ); + } +} + +/* the following is the stuff on the old code.c file */ + +branch( n ) +{ + /* output a branch to label n */ + if( !reached ) return; + printf( "\tjpr\tL%d\n", n ); +} + +deflab( n ) +{ + /* output something to define the current position as label n */ + printf( "L%d:\n", n ); +} + +defalign(n) +register n; +{ + /* cause the alignment to become a multiple of n */ + n /= SZCHAR; + if( curloc != PROG && n > 1 ) printf( "\t.even\n" ); +} + +char *locnames[] = +{ + /* location counter names for PROG, ADATA, DATA, ISTRNG, STRNG */ + "\t.psec\n\t.code\n", + 0, + "\t.psec\t%s\n\t.data\n", + 0, + "\t.psec\tstr%s\n\t.data\n", +}; + +eccode(blevel) +int blevel; +{ + ; /* called at end of every block */ +} + +efcode() +{ + /* code for the end of a function */ + + deflab( retlab ); /* define the return location */ + + efdebug(); /* end of function debug info */ + + if( strftn ) + { + /* copy output to caller */ + printf( "\tldl\trr2,#___StRet\n" ); + } + + printf("\tadd\tsp,#~L2-%%c\n\tldm\tr8,@SP,#6\n\tinc\tsp,#12\n"); + printf("\tret\n"); +} + +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 + */ + +#ifdef STKCK + register spgrow_lbl; + extern int stkckflg; +#endif + +#ifdef PROFILE + extern int proflg; + + /* + ** code to provide profiling via prof(1) + ** + */ + if( proflg ) + { + register int i; + + i = getlab(); + printf(" mov.l &L%%%d,%%a0\n", i); + printf(" jsr mcount%%\n"); + printf(" data\n"); + printf(" even\n"); + printf("L%%%d:\n", i); + printf(" long 0\n"); + printf(" text\n"); + } +#endif PROFILE + +#ifdef STKCK + + /* + ** code needed for M68000 to check stack growth + ** against current splimit%. if we are about to + ** exceed current limit, ask system for more stack. + ** + */ + + if( stkckflg ) /* if stack checking requested */ + { + spgrow_lbl = getlab(); + printf( " lea.l F%%%d-256(%%sp),%%a0\n", ftnno ); + printf( " cmp.l %%a0,splimit%%\n" ); + printf( " bhi.b L%%%d\n", spgrow_lbl ); + printf( " jsr spgrow%%\n" ); + deflab( spgrow_lbl ); + } +#endif + + + retlab = getlab(); + + /* routine prolog */ + + printf("\t{\n\tdec\tsp,#12\n\tldm\t@SP,r8,#6\n\tsub\tsp,#~L2-%%c\n"); + printf("\tld\tfp,sp\n\tld\t@SP,#~L2-4\n"); +/* printf( " movm.l &M%%%d,S%%%d(%%fp)\n", ftnno, ftnno ); */ + + bfdebug( a, n ); /* do debug info at fcn begin */ +} + +defnam( p ) +register struct symtab *p; +{ + /* define the current location as the name p->sname + * first give the debugging info for external definitions + */ + if( p->slevel == 0 ) /* make sure it's external */ + prdef(p,0); + + if( p->sclass == EXTDEF ) + printf( "_%s::\n", exname( p->sname ) ); +/* printf( " global %s\n", exname( p->sname ) ); */ + else + printf( "_%s:\n", exname( p->sname ) ); +} + +/*static char *xtab[] = +{ + "0x00", "0x01", "0x02", "0x03", "0x04", "0x05", "0x06", "0x07", + "'\\b", "'\\t", "'\\n", "'\\v", "'\\f", "'\\r", "0x0e", "0x0f" +}; */ +bycode( t, i ) +register 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( "\t.byte\t" ); + else + printf( "," ); +/* if((t=='\\') || (t=='\'')) + printf("'\\%c",t); + else if((t > ' ') && (t <= '~')) + printf( "'%c",t); + else if(t <= 0x0f) + printf("%s",xtab[t]); + else + printf( "0x%x", t ); +*/ + printf( "%%%x", t ); + if( i == 07 ) + printf( "\n" ); + } +} + +zecode( n ) +register n; +{ + /* n integer words of zeros */ + register OFFSZ temp; + + if( n <= 0 ) return; + printf( "\t.=.+%d\n", (SZINT/SZCHAR)*n ); + temp = n; + inoff += temp*SZINT; +} + +main( argc, argv ) +char *argv[]; +{ + register r; +#ifdef BLIT + char errbuf[BUFSIZ]; + + setbuf(stderr, errbuf); +#endif + + r = mainp1( argc, argv ); + return( r ); +} + + +/* +** generate switch/case construct +*/ +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 long j, range; + register dlab, swlab; /* default label, bottom-of-switch label */ + register svallab; + + range = p[n].sval - p[1].sval; + + /* table is faster & shorter for density > 20% - JGH */ + /* direct: overhead=2 (for br); increment: 5*n */ + /* table: overhead=15; increment: 1*(range+1) */ + +/* + if(range+14 <= 5*n) +*/ + dlab = p->slab >= 0 ? p->slab : getlab(); + if(range <= 3 * n) + + { + /* implement a direct switch */ + + if( p[1].sval) + { +/* + printf( " sub.w &%ld,%%d0\n", p[1].sval ); +*/ + if ((unsigned)p[1].sval <= 16) + printf( " dec r2,#%%%x\n", (unsigned short) p[1].sval ); + else + printf( " sub r2,#%%%x\n", (unsigned short) p[1].sval ); + } + + /* note that this is a logical compare; it thus checks + ** for numbers below range as well as out of range. + */ +/* + printf( " cmp.w %%d0,&%ld\n", range ); +*/ + printf( " cp r2,#%%%lx\n", range ); + +/* + printf( " bhi L%%%d\n", dlab ); + + printf( " add.w %%d0,%%d0\n" ); +/* Assume "swbeg &n" takes 4 bytes: 2 for swbeg, 2 for # of cases */ +/* + printf( " mov.w 10(%%pc,%%d0.w),%%d0\n" ); + printf( " jmp 6(%%pc,%%d0.w)\n" ); + printf( " swbeg &%d\n", range+1 ); + /* range runs from zero, so add 1 for cases */ + printf( " jpr ugt,L%d\n", dlab ); + + printf( " rl r2,#2\n" ); + swlab = getlab(); + printf( " ldl rr4,L%d(r2)\n", swlab); + printf( " jp @rr4\n" ); + xxx((range + 1) << 2); + printf( "\t.psec %s\n\t.data\n\t.even\nL%d:\n", datanm, swlab); +/* + deflab( swlab = getlab() ); +*/ + + + /* output table */ + + for( i=1, j=p[1].sval; i<=n; ++j ) + { +/* + printf( " short L%%%d-L%%%d\n", + (j == p[i].sval) ? p[i++].slab : dlab, swlab ); +*/ + printf( "\t.addr\tL%d\n", + (j == p[i].sval) ? p[i++].slab : dlab); + } + printf("\t.psec\n\t.code\n"); + + if( p->slab < 0 ) + deflab( dlab ); + return; + } + /* out for the moment + ** if( n >= 4 ) + ** werror( "inefficient switch: %d, %d", n, (int) (range/n) ); + */ + + /* simple switch code */ + + if(n < 10) { + for( i=1; i<=n; ++i ) + { + /* already in 0 */ + if( p[i].sval ) +/* + printf( " cmp.w %%d0,&%ld\n", p[i].sval ); + else + printf( " tst.w %%d0\n" ); +*/ + printf( "\tcp\tr2,#%%%x\n", (unsigned short) p[i].sval ); + else + printf( "\ttest\tr2\n" ); +/* + printf( " beq L%%%d\n", p[i].slab ); +*/ + printf( "\tjpr\teq,L%d\n", p[i].slab ); + } + + if( p->slab >= 0 ) +/* + printf( " br L%%%d\n", p->slab ); +*/ + printf( "\tjpr\tL%d\n", p->slab ); + return; + } + /* hashswitch */ + svallab = getlab(); + swlab = getlab(); + printf("\tldl\trr4,#L%d\n", svallab); + printf("\tld\tr3,#%%%x\n", n); + printf("\tcpir\tr2,@rr4,r3,eq\n"); + printf("\tjpr\tne,L%d\n", dlab); + printf("\tsll\tr3,#2\n"); + printf("\tneg\tr3\n"); + printf("\tldl\trr4,L%d+%%%x(r3)\n", swlab, (n - 1) << 2); + printf("\tjp\t@rr4\n"); + xxx((n << 1) + (n << 2)); + printf("\t.psec %s\n\t.data\n\t.even\nL%d:\n", datanm, svallab); + for(i = 1; i <= n; i++) + printf("\t.word\t%%%x\n", (unsigned short) p[i].sval); + deflab(swlab); + for(i = 1; i <= n; i++) + printf("\t.addr\tL%d\n", p[i].slab); + printf("\t.psec\n\t.code\n"); + if(p->slab < 0) + deflab(dlab); +} + +#ifdef TWOPASS +/* + * Code added from common/reader.c to make 2 pass version + * + */ + + +#ifndef NODBG +e2print( p ) +register NODE *p; +{ + printf( "\n********* costs=(0,...,NRGS;EFF;TEMP;CC)\n" ); + e22print( p ,"T"); + printf("=========\n"); +} + +e22print( p ,s) +register NODE *p; +char *s; +{ + static down=0; + register ty; + + ty = optype( p->tn.op ); + if( ty == BITYPE ) + { + ++down; + e22print( p->in.right ,"R"); + --down; + } + e222print( down, p, s ); + + if( ty != LTYPE ) + { + ++down; + e22print( p->in.left, "L" ); + --down; + } +} + +e222print( down, p, s ) +NODE *p; +char *s; +{ + /* print one node */ + int i, d; + + for( d=down; d>1; d -= 2 ) printf( "\t" ); + if( d ) printf( " " ); + + printf( "%s.%d) op= '%s'",s, (int)(p-node), opst[p->in.op] ); + switch( p->in.op ) + { + /* special cases */ + case REG: + printf( " %s", p->tn.rval ); /* Changed form reader. */ + break; + + case ICON: + case NAME: + case VAUTO: + case VPARAM: + case TEMP: + printf( " " ); + printf(" %s", p->in.name ); + break; + + case STCALL: + case UNARY STCALL: + printf( " args=%ld", p->stn.argsize ); + case STARG: + case STASG: + printf( " size=%ld", p->stn.stsize ); + printf( " align=%d", p->stn.stalign ); + break; + + case GENBR: + printf( " %d (%s)", p->bn.label, opst[p->bn.lop] ); + break; + + case CALL: + case UNARY CALL: + printf( " args=%ld", p->stn.argsize ); + break; + + case GENUBR: + case GENLAB: + printf( " %d", p->bn.label ); + break; + + case FUNARG: + printf( " offset=%d", p->tn.rval ); + + } + + printf( ", %d\n", p->in.type ); + printf( "\n" ); +} + +# else +e2print( p ) +NODE *p; +{ + werror( "e2print not compiled" ); +} +e222print( p, s ) +NODE *p; +char *s; +{ + werror( "e222print not compiled" ); +} +# endif +/* + * End of code added from common/reader.c to make 2 pass version + * + */ +#endif TWOPASS diff --git a/WEGA/contrib/lcc/cmd/comp/u8k/local2.c b/WEGA/contrib/lcc/cmd/comp/u8k/local2.c new file mode 100644 index 0000000..24c3386 --- /dev/null +++ b/WEGA/contrib/lcc/cmd/comp/u8k/local2.c @@ -0,0 +1,1227 @@ +# include "mfile2.h" +#ifndef NONAME +#define NONAME 040000 +#endif + +int rsmask; + +/* the stack frame looks as follows: +** +** incoming args +** saved PC (4 bytes) +** saved old FP (rr12) (4 bytes) +** saved regs (rr10, rr8) +** autos (maxboff keeps track of this) +** temps (maxtemp keeps track of this) +** 2 byte field for offset to saved FP +** SP,FP-> +** the first temp begins at FP + 2 +** the last temp ends at FP + ~L1 +** the first auto begins at FP + ~L1 +** the last auto ends at FP + ~L2 - 12 +** rr8 is saved at FP + ~L2 - 12 +** rr10 is saved at FP + ~L2 - 8 +** rr12 (the old FP) is saved at FP + ~L2 - 4 +** the first arg begins at FP + ~L2 + 4 +*/ + +static char rnm[5]; +#define HIGHREG 0x40 +#define NFLG 0x7 + + +/* retun number of bytes for type t */ +typlen(t) +{ + if(t & (TLONG |TULONG| TPOINT | TFLOAT)) + return(4); + else if (t & (TUCHAR | TCHAR)) + return(1); + else if ( t & TDOUBLE) + return(8); + else + return(2); +} + +char * +prnames(typ, val, lab) +register typ, val; +register lab; +{ + char *s; + register int errorf; +if(rdebug > 2) + printf("typ = 0x%x val = %d lab = %d\n",typ,val,lab); + errorf = 0; + s = rnm; + *s = '?'; + *(s+1) = '\0'; + switch(typlen(typ)) + { + case 1: + if((val & 0xf) > 7) + errorf = 1; + if(HIGHREG & val) + sprintf(s, "rh%d",(val & 0xf)); + else sprintf(s, "rl%d",val); + break; + case 2: + if(lab==2) + goto lll; + if(lab==4) + goto ddd; +sss: + if(val > 11) + errorf = 1; + sprintf(s, "r%d",val); + break; + case 4: + if(lab==4) + goto ddd; + if(lab==1) + goto sss; +lll: + if(val & 1 || val > 11) + errorf = 1; + sprintf(s, "rr%d",val); + break; + case 8: + if(lab==2) + goto lll; + if(lab==1) + goto sss; +ddd: + if(val & 3 || val > 8) + errorf = 1; + sprintf(s, "rq%d",val); + break; + default: + werror("bad register type (length = %d)",typlen(typ)); + } + if(errorf) + werror("bad register value %d, length = %d",val, + typlen(typ)); + return s; +} + + +lineid( l, fn ) +char *fn; +{ + /* identify line l and file fn */ + printf( "%s line %d, file %s\n", COMMENTSTR, l, fn ); +} + +eobl2() +{ + register off; + register rsave; + register i, m; + /* count bits in rsmask */ + for( rsave=i=0, m=1; i<16; ++i, m<<=1 ) + { + if( m&rsmask ) rsave += 4; + } + maxboff /= SZCHAR; + maxtemp /= SZCHAR; + maxarg /= SZCHAR; + + off = maxtemp + 2; + /* space for temps + 2 bytes for offset to old frame pointer */ + printf("\t~L1 := %d\n", off); + off += maxboff; /* space for automatics */ + off += 12; /* 12 bytes for saved registers */ + printf("\t~L2 := %d\n\t}\n", off); + rsmask = 0; + eobl2dbg(); /* very end debug code */ +} + +special( sh, p ) +NODE *p; +register sh; +{ + register int val; + + sh &= SVMASK; /* clear all but the special code */ + switch (sh) + { + case 1: /* power of 2 */ + case 2: /* sum of 2 powers of 2 */ + case 3: /* difference of 2 powers of 2 */ + + if (p->tn.op != ICON || p->tn.name != (char *) 0) + return(0); + val = p->tn.lval; + if (sh == 1) /* power of 2 */ + return (val > 0 && (val & (val-1)) == 0); + else if (sh == 2 && val > 0) /* sum of powers of 2 */ + { + /* (word) multiply faster than shift by >12 on 68010 */ +/* shift is always faster + if (!(p->tn.type & (TLONG | TULONG)) && val > 4096) + return(0); +*/ + return ((val &= (val-1)) != 0 && (val & (val-1)) == 0); + } + else if (sh == 3 && val > 0) /* diff of powers of 2 */ + { + /* (word) multiply faster than shift by >12 on 68010 */ +/* + if (!(p->tn.type & (TLONG | TULONG)) && val > 4096) + return(0); +*/ + while ((val & 1) == 0) /* get to '00..011...1' */ + val >>= 1; + return ((val & (val+1)) == 0); + } + else + return(0); + break; + + default: + e2print(p); + cerror( "special called!" ); + return( INFINITY ); + } +} + +static int toff; +static int toffbase; + +popargs( size ) +register size; +{ + /* pop arguments from the stack */ + toff -= size/2; + if( toff == 0 ) + { + size -= 2*toffbase; + toffbase = toff = 0; + } + if(!size) + return; + +/* + printf( " add.l &%d,%%sp\n", size ); +*/ + if (size <= 16) + printf("\tinc\tsp,#%%%x\n", size); + else + printf("\tadd\tsp,#%%%x\n", (unsigned short)size); +} + + +/* print the address of p+d */ +next_address( p, d, typ, flg) +register NODE *p; +register int d; /* the displacement */ +register int typ; +{ + register NODE *ptemp,*r,*l; + + if (d) { + ptemp = talloc(); + *ptemp= *p; + if(d == NFLG) d -= NFLG; + ptemp->tn.type = typ; + switch ( ptemp->in.op ) + { + case REG: + ptemp->bn.label = typlen(typ)>>1; + if((!d)&&(typ == TCHAR)) + ptemp->tn.rval |= HIGHREG; + ptemp->tn.rval += (d / 2); + break; + case TEMP: /* temps may be in registers */ + if (ptemp->tn.rval) + goto bad; + /* else FALLTHRU */ + case ICON: + if(p->in.name == (char *)0 && p->tn.rval == NONAME) { + if(typlen(typ)==2) { + if(!d) + ptemp->tn.lval >>= 16; + ptemp->tn.lval &= 0xffff; + break; + } else if (typlen(typ)==1) { + if(!d) + ptemp->tn.lval >>= 8; + ptemp->tn.lval &= 0xff; + break; + } + } + case NAME: + case VAUTO: + case VPARAM: + ptemp->tn.lval += d; + break; + case STAR: + p = p->in.left; + switch( p->in.op ) + { + case REG: + /* form ( STAR (PLUS REG ICON(4) ) */ + l = ptemp->in.left = talloc(); + *l = *p; /* copy type and other info */ + l->tn.op = PLUS; + l->in.left = talloc(); /* copy REG node */ + *(l->in.left ) = *p; /* copy REG node */ + r = l->in.right = talloc(); /* node for icon */ + *r = *p; /* copy type and other info */ + r->tn.op = ICON; + r->tn.lval = d; + break; + + case MINUS: + if (p->in.right->in.op != ICON) + goto bad; + d = -d; + /* FALL THRU */ + case PLUS: + if (p->in.right->in.op == ICON) + { + /* Make copy of address tree with ICON */ + /* modified by adding d */ + l = ptemp->in.left = talloc(); + *l = *p; /* copy PLUS node */ + r = l->in.right = talloc(); + *r= *(p->in.right); /* copy ICON node */ + if ( r->in.op != ICON ) goto bad; + r->tn.lval += d; + l->in.left = talloc(); + l = l->in.left; + p = p->in.left; + *l = *p; /* make copy of either REG or REG+REG */ + if( l->in.op == REG ) break; /* Done with copy */ + if( l->in.op != PLUS) goto bad; /* Bad address tree */ + l->in.right=talloc(); /* Copy REG */ + *(l->in.right) = *(p->in.right); /* Copy REG */ + l->in.left = talloc(); + l = l->in.left; + p = p->in.left; + *l = *p; /* Copy REG or CONV */ + if( l->in.op == REG ) break; /* Done with copy */ + if( l->in.op != CONV) goto bad; /* Bad address tree */ + l->in.left=talloc(); /* Copy REG */ + *(l->in.left) = *(p->in.left); /* Copy REG */ + break; + + } + else if (p->in.right->in.op == REG) + { + /* Make copy of address tree with ICON */ + /* adding d */ + l = ptemp->in.left = talloc(); + *l = *p; /* copy PLUS node */ + r = l->in.right = talloc(); + *r = *p; + r->tn.op = ICON; + r->tn.lval = d; + l->in.left = talloc(); + l = l->in.left; + *l = *p; /* copy PLUS node */ + r = l->in.right = talloc(); + *r= *(p->in.right); /* copy REG node */ + l->in.left = talloc(); + *(l->in.left) = *(p->in.left); /* make copy of REG */ + break; + } + + default: goto bad; + }; + break; + default: + goto bad; + } /* switch */ + + if(flg) + nadrput(ptemp); + else + adrput( ptemp ); + tfree( ptemp ); + } + else { + if(flg) + nadrput(p); + else + adrput(p); + } + return; +bad: + e2print( ptemp ); + cerror("Illegal byte address (ZB)\n"); + return(-1); +} + +zzzcode( p, ppc , q) +register NODE *p; +register char **ppc; +OPTAB *q; +{ + register int c; + register int ii; + register NODE *newp, *tnode; + register int displ,t; + TWORD ht; + + static int labels[10]; /* labels for use in patterns */ + + switch( c= *++(*ppc) ) + { +/* + case 'p': + popargs( 4 ); + return; + case 'q': + popargs( 8 ); + return; +*/ + case 'c': + popargs((short)(p->stn.argsize/SZCHAR)); + return; +/* + case '1': + if( toff ) + { + putchar( '-' ); + } + printf( "(%%sp)" ); + if( !toff ) toffbase = 1; + ++toff; + return; + + case '2': + if( toff ) + { + putchar( '-' ); + } + printf( "(%%sp)" ); + if( !toff ) toffbase = 2; + toff+=2; + return; + + case '0': + /* like 2 but doesn't print -(%%sp) */ + /* used for pea. leaves toffbase at 0, also */ +/* toff += 2; + return; +*/ + case 's': /* like s, but needs value afterwards */ + case 'S': /* structure assignment */ + if( p->in.op == STASG ) + { + stas( p, p->stn.stsize, c); + } + else if( p->in.op == STARG ) + { + /* store an arg onto the stack */ + star( p->in.left, p->stn.stsize ,q); + } + else + { + e2print(p); + cerror( "ZS bad" ); + } + break; + + case 'z': /* adjust register on right */ + { + register long adj = p->stn.stsize; + if( adj == SZSHORT || adj == SZLONG ) return; + adj /= SZCHAR; + if( adj > 16) + printf( "\tsub\t%s,#%%%x\n", + prnames(TINT, p->in.right->tn.rval+1, 0), (unsigned short)adj); + else if( adj) + printf( "\tdec\t%s,#%%%x\n", + prnames(TINT, p->in.right->tn.rval+1,0), adj); + } + return; + + case 'I': + cbgen( p->bn.lop, (int)(p->bn.label), c ); + return; + + case 'i': + ++*ppc; + p = getadr(p,ppc); + printf("%s",prnames(TINT,p->tn.rval,0)); + + /* c = p->in.left->in.left->tn.rval; /* register number */ + /* dbccgen( p->bn.lop, p->bn.label, c );*/ + return; + + case 'b': + ++*ppc; + p = getadr(p,ppc); + if((ii = ispow2(p->tn.lval))>=0) + { + printf( "#%%%x", ii ); + break; + } + cerror( "Zb but not power of 2" ); + + case 'n': +/* ++*ppc; + next_address( getadr(p,ppc), 4 ); +*/ + displ = ((*++(*ppc)) - '0'); + if(!displ) displ += NFLG; /* da 'B' auch next_address nutzt */ + switch(*++(*ppc)) { + case 'c': t = TCHAR; break; + case 's': t = TINT; break; + case 'l': t = TLONG; break; + case 'd': t = TDOUBLE; break; + } + ++*ppc; + ii = 0; + if(**ppc == 'B') { + **ppc = 'A'; + ii = 1; + } + next_address( getadr(p,ppc), displ, t , ii); + break; + + case 'y': /* CONV reg to shorter reg */ + /* CONV for regvar in char only in scatchregs */ + { char qt,zt; + qt = *++(*ppc); + zt = *++(*ppc); + ++*ppc; + tnode = getadr(p,ppc); + if(zt == 'c') { + ++*ppc; + newp = getadr(p,ppc); + if(newp->tn.type&TCHAR) + newp->tn.type=(~TCHAR&newp->tn.type)| + TSHORT; + else + if(newp->tn.type&TUCHAR) + newp->tn.type=(~TUCHAR&newp->tn.type)| + TUSHORT; + else cerror(" bad 'CONV' registertype "); + ht = newp->tn.type; + if((tnode->tn.rval & 0xf) > 7 ) { + printf("\tld\t"); + adrput(newp); + putchar(','); + if(qt == 'l') { + tnode->tn.rval++; + tnode->tn.type = TINT; + } + adrput(tnode); + putchar('\n'); + } + else { + *newp = *tnode; + if(qt == 'l') { + newp->tn.rval++; + } + newp->tn.type = ht; + newp->bn.label = 1; + } + } + if(zt == 's') { + if(tnode->tn.type&TLONG) + tnode->tn.type=(~TLONG&tnode->tn.type)| + TSHORT; + else + if(tnode->tn.type&TULONG) + tnode->tn.type=(~TULONG&tnode->tn.type)| + TUSHORT; + else + if(tnode->tn.type&TPOINT) + tnode->tn.type = + ((~TPOINT & tnode->tn.type) & ~BTMASK)| + TSHORT; + else cerror(" bad 'CONV' registertype "); + rfree(tnode->tn.rval,1); + tnode->tn.rval++; + tnode->bn.label = 1; + } + } + break; + + + case 'f': /* shift by number of lowest bit on */ + ++*ppc; + newp = getadr(p, ppc); + c = newp->tn.lval; + if (c > 0) + { + for (ii = 0; (c & 1) == 0; ii++) + c >>= 1; + doshift(ii, ppc, p); + } + else + cerror( "Zf on zero or negative value" ); + break; + + case 'd': /* shift by diff. of powers of 2 (for sums of powers) */ + ++*ppc; + newp = getadr(p, ppc); + c = newp->tn.lval; + if (c > 0) + { + while ((c & 1) == 0) + c >>= 1; + if ((c >>= 1) != 0 && (c & (c-1)) == 0) /* 1 bit left */ + { + for (ii = 1; (c & 1) == 0; ii++) + c >>= 1; + doshift(ii, ppc, p); + break; + } + } + cerror( "Zd on improper value" ); + break; + + case 'D': /* shift by diff. of powers of 2 (for diff.) */ + ++*ppc; + newp = getadr(p, ppc); + c = newp->tn.lval; + if (c > 0) + { + while ((c & 1) == 0) /* get to '00...011...1' */ + c >>= 1; + if (c != 0 && (c & (c+1)) == 0) /* string of 1's */ + { + for (ii = 0; (c & 1); ii++) /* count 1's */ + c >>= 1; + doshift(ii, ppc, p); + break; + } + } + cerror( "ZD on improper value" ); + break; + + case 'B': /* byte address for a bset, bclr */ + ++*ppc; + newp = getadr(p, ppc); + if((ii = ispow2(newp->tn.lval)) < 0) + { + cerror( "ZB but not power of 2" ); + return; + } + if(typlen(newp->tn.type)==1) + ii&=7; + printf("#%%%x", ii); /* output the bit number (mod 8) */ + break; + + case 't': /* take address of temp */ + ++*ppc; + newp = getadr(p, ppc); /* the temp */ + ++*ppc; + p = getadr(p, ppc); /* the result reg */ + if (newp->tn.rval == 0) /* memory temp? */ + { + printf("\tldl\t"); + adrput(p); + printf(",FP\n\tadd\t"); + next_address(p, 2, TINT, 0); + printf(",#%%%x\n", (unsigned short)(2+(int)newp->tn.lval)); + break; + } + tnode = talloc(); /* the memory temp */ + *tnode = *newp; /* copy stuff */ + tnode->tn.lval = freetemp((OFFSZ)1); /* get a memory temp */ + tnode->tn.lval = BITOOR(tnode->tn.lval); + tnode->tn.rval = 0; /* not in register */ + if( typlen(tnode->tn.type) >= 4) + c = 'l'; /* move long */ + else if(typlen(tnode->tn.type)==2) + c = ' '; /* move word */ + else + c = 'b'; /* move byte */ + printf("\tld%c\t", c); + adrput(tnode); + putchar(','); + adrput( newp ); + if(typlen(tnode->tn.type) == 8) { + printf("\tldl\t"); + next_address(tnode, 4, TLONG, 0); + putchar(','); + next_address(newp, 4, TLONG, 0); + } + printf("\tldl\t"); + adrput(p); + printf(",FP\n\tadd\t"); + next_address(p, 2, TINT, 0); + printf(",#%%%x\n", (unsigned short)(2+(int)tnode->tn.lval)); + tfree( tnode ); + break; + + case 'L': /* first use of label in pattern */ + case 'l': /* other uses of label in pattern */ + ii = *++(*ppc) - '0'; /* label number */ + if (ii < 0 || ii > 9) + cerror( "illegal %c code: %c", c, ii+'0'); + if (c == 'L') /* define it */ + labels[ii] = getlab(); + printf("L%d", labels[ii]); + break; + + default: + e2print(p); + cerror( "illegal zzzcode: %c", c ); + } +} + +/* put a shift left of size s of register A? from string "sA?" */ +doshift (n, ppc, p) + register int n; + register char **ppc; + register NODE *p; + { + register char size; + register unsflg = 0; + + size= *++(*ppc); + if(size == 'u') { + size = *++(*ppc); + unsflg++; + } + + if(size == 's') + size = ' '; + ++*ppc; + p = getadr(p, ppc); + if (n == 1) + { + printf("\tadd%c\t", size); + adrput(p); + putchar(','); + adrput(p); + putchar('\n'); + } + else if (n > 1) + { + if(unsflg) + printf("\tsll%c\t",size); + else + printf("\tsla%c\t",size); + adrput(p); + printf(",#%%%x\n", n); +/* + putchar('\n'); +*/ + } + /* null for shift of 0 */ + } + +star( p, sz , q) +register NODE *p; +OFFSZ sz; +OPTAB *q; +{ + /* put argument onto the stack */ + /* p is a REG */ + + if( p->tn.op != REG ) uerror( "star of non-REG" ); +/* + sz /= (SZCHAR << 1); +*/ + sz /= SZCHAR; + +/* + if(sz > 2) { +*/ + if(sz > 4) { /* mit ldir */ + char rn[4]; + char *dec = "dec"; + if(sz > 16) + dec = "sub"; + strcpy(rn, prnames(TINT, resc[0].tn.rval,0)); + printf("\tld\t%s,#%%%x\n",rn,(unsigned short)sz); + printf("\tsub\tsp,%s\n",rn); + printf("\tld\t@SP,#0\n\tldirb\t@SP,@%s,%s\n", + prnames(TLONG,p->tn.rval,0) ,rn); + printf("\t%s\tsp,#%%%x\n",dec,(unsigned short)sz); + } else + printf("\tpush%c\t@SP,%s\n",((sz==4)?'l':' '), + prnames((sz==4)?TLONG:TINT, p->tn.rval,0)); + +} + +stas( p, sz, c ) +register NODE *p; +OFFSZ sz; +register c; +{ + /* p is an STASG node; left and right are regs */ + /* all structures are aligned on int boundaries */ + + register rn, ln, zz, scn; + + rn = p->in.right->tn.rval; + if( c == 's' ) + { + /* lhs is a temp moved into a reg: kluge! */ + ln = resc[0].tn.rval; /* A1 */ + scn = resc[1].tn.rval; /* A2 */ + } + else { + ln = p->in.left->tn.rval; + scn = resc[0].tn.rval; /* A1 */ + } + + zz = (sz /= SZCHAR) >> 1; + if(zz > 2) { + char * dec = "dec"; + if(zz > 8) + dec = "sub"; + printf("\tld\t%s,#%%%x\n",prnames(TINT, scn,0), (unsigned short)zz); + printf("\tldir\t@%s,",prnames(TLONG,ln,0)); + printf("@%s,",prnames(TLONG,rn,0)); + printf("%s\n",prnames(TINT,scn,0)); + if( (ln & 0xf) > 7) /* regvar */ + /* restore clobbered register variable */ + printf( "\t%s\t%s,#%%%x\n",dec, + prnames(TINT, ln+1,0), (unsigned short)sz); + if( (rn & 0xf) > 7) /* regvar */ + /* restore clobbered register variable */ + printf( "\t%s\t%s,#%%%x\n",dec, + prnames(TINT, rn+1,0), (unsigned short)sz); + } else if(zz == 2) { + printf("\tldl\trx0,@r%s\n",prnames(TLONG, rn,0)); + printf("\tldl\t@r%s,rx0\n",prnames(TLONG, ln,0)); + } else if (zz == 1) { + printf("\tld\tx0,@r%s\n",prnames(TINT, rn,0)); + printf("\tld\t@r%s,x0\n",prnames(TINT, ln,0)); + } else { + e2print(p); + cerror( "ZS sz %ld", sz ); + } +} + +conput( p ) +register NODE *p; +{ + char *s; + int typ; + switch( p->in.op ) + { + case ICON: + acon( p ); + return; + case REG: + printf("%s", prnames(p->tn.type, p->tn.rval,p->bn.label)); + return; + default: + e2print(p); + cerror( "illegal conput" ); + } +} + +insput( p ) +NODE *p; +{ + e2print(p); + cerror( "insput" ); +} + +#ifdef UPPUT + +upput( pp ) +register NODE *pp; +{ + /* output the address of the second word in the + ** pair pointed to by p (for LONGs) + */ + register long v; + register NODE *r, *l, *p; + + v=0; + p = pp; + if( p->tn.op == PLUS ) + { +/* + v=0; + r = p->in.right; + l = p->in.left; + if( r->tn.op == ICON && l->tn.op == PLUS ) + { + v = r->tn.lval; + p = l; + r = p->in.right; + l = p->in.left; + } + if( r->tn.op == REG ) + { + l = p->in.left; + if( l->tn.op == REG ) + { + printf( "%%%lx(%%a%d,%%d%d.l)", v, r->tn.rval, + l->tn.rval ); + return; + } + if( l->tn.op != CONV ) goto ill; + l = l->in.left; + if( l->tn.op != REG ) goto ill; + printf("%%%lx(%%a%d,%%d%d.w)",v,r->tn.rval,l->tn.rval); + return; + } +not by Z8000 */ + if( r->tn.op != ICON ) goto ill; + v = r->tn.lval; + p = p->in.left; + } + else if( p->tn.op == MINUS ) + { + r = p->in.right; + if( r->tn.op != ICON || r->in.name != (char *) 0 ) goto ill; + v = -r->tn.lval; + p = p->in.left; + } + if( p->tn.op != REG ) goto ill; + if( v ) +/* + printf( "%%%lx(%%a%s)", v, rnames[p->tn.rval] ); + else + printf( "(%%a%s)", rnames[p->tn.rval] ); +*/ + printf( "_stkseg+%%%x(%s)",(unsigned short) v, prnames(TLONG,p->tn.rval,0) ); + else + printf( "@%s", prnames(TLONG,p->tn.rval,0) ); + return; +ill: + e2print(pp); + cerror( "illegal address: upput" ); +} + +#else +upput( pp ) +register NODE *pp; +{ + /* output the address of the second word in the + ** pair pointed to by p (for LONGs) + */ + if( pp->tn.op == REG ) { + printf( "@%s", prnames(TLONG,pp->tn.rval,0) ); + return; + } + e2print(pp); + cerror( "illegal address: upput" ); +} +#endif UPPUT + +adrput( p ) +register NODE *p; +{ + /* output an address, with offsets, from p */ + + while( p->in.op == FLD || p->in.op == CONV ) + { + p = p->in.left; + } + switch( p->in.op ) + { + + case NAME: + acon( p ); + sideff = 0; + return; + + case ICON: + /* addressable value of the constant */ + printf( "#" ); + acon( p ); + sideff = 0; + return; + + case REG: + conput( p ); + sideff = 0; + return; + + case STAR: + upput( p->in.left ); + return; + + case VAUTO: + if ((int)p->tn.lval < 0) + printf( "_stkseg+~L1-%%%x(fp)", (unsigned short)(-(p->tn.lval)) ); + else + printf( "_stkseg+~L1+%%%x(fp)", (unsigned short) (p->tn.lval) ); + sideff = 0; + return; + + case VPARAM: + if ((int)p->tn.lval < 0) + printf( "_stkseg+~L2-%%%x(fp)", (unsigned short)(-(p->tn.lval)) ); + else + printf( "_stkseg+~L2+%%%x(fp)", (unsigned short) p->tn.lval ); + sideff = 0; + return; + + case TEMP: + if (p->tn.rval) + { + register int i = (int)p->tn.lval; + + printf("%s", prnames(p->tn.type, i, 0)); + } + else + printf( "_stkseg+%%%x(fp)", (unsigned short)(2 + p->tn.lval)); + sideff = 0; + return; + + default: + e2print(p); + cerror( "illegal address" ); + return; + } +} + +/* lda ala OF */ +padrput( p ) +register NODE *p; +{ + /* output an address, with offsets, from p */ + + switch( p->in.op ) + { + + case VAUTO: + /* offset only !!! without FP */ + if ((int)p->tn.lval < 0) + printf( "#~L1-%%%x", (unsigned short)(-(p->tn.lval)) ); + else + printf( "#~L1+%%%x", (unsigned short)(p->tn.lval) ); + sideff = 0; + return; + + case VPARAM: + /* offset only !!! without FP */ + if ((int)p->tn.lval < 0) + printf( "#~L2-%%%x", (unsigned short)(-(p->tn.lval)) ); + else + printf( "#~L2+%%%x", (unsigned short)(p->tn.lval) ); + sideff = 0; + return; + + default: + e2print(p); + cerror( "illegal address" ); + return; + } +} + +/* for BA-addressing in ld-Operations */ +nadrput( p ) +register NODE *p; +{ + /* output an address, with offsets, from p */ + + switch( p->in.op ) + { + + case VAUTO: + if ((int)p->tn.lval < 0) + printf( "FP(#~L1-%%%x)", (unsigned short)(-(p->tn.lval)) ); + else + printf( "FP(#~L1+%%%x)", (unsigned short) (p->tn.lval) ); + sideff = 0; + return; + + case VPARAM: + if ((int)p->tn.lval < 0) + printf( "FP(#~L2-%%%x)", (unsigned short)(-(p->tn.lval)) ); + else + printf( "FP(#~L2+%%%x)", (unsigned short) p->tn.lval ); + sideff = 0; + return; + + } + adrput( p ); +} + +acon( p ) +register NODE *p; +{ + /* print out a constant */ + + if( p->in.name != (char *) 0) { + /* names */ + switch(p->tn.rval) { + case 0x1000: + printf("^s _%s", p->in.name ); + return; + case 0x2000: + printf("^o _"); + break; + case 0x9000: + printf("^s %s", p->in.name ); + return; + case 0xa000: + printf("^o "); + break; + case 0x3000: + printf("_%s(",p->in.name); + prnames(TINT,(int)p->tn.lval,0); + putchar(')'); + return; + default: + if(p->tn.rval >= 0 || *(p->in.name)!='L') + putchar('_'); + } + printf("%s", p->in.name ); + if(p->tn.lval) + putchar('+'); + else + return; + } else if(typlen(p->tn.type) >= 4 ) { + printf( "%%%lx", p->tn.lval); + return; + } + printf( "%%%x", (unsigned short)p->tn.lval); +} + +/* alte version +acon( p ) +register NODE *p; +{ + if( p->in.name == (char *) 0) + { + if(typlen(p->tn.type) < 4) + printf( "%%%x", (unsigned short) p->tn.lval); + else + printf( "%%%lx", p->tn.lval); + } else if( p->tn.rval == 0x2000 ) { + printf("^o _%s",p->in.name); + } else if( p->tn.rval == 0x1000 ) { + printf( "^s _%s", p->in.name ); + } else if( p->tn.rval == 0xa000 ) { + printf("^o %s",p->in.name); + } else if( p->tn.rval == 0x9000 ) { + printf( "^s %s", p->in.name ); + } else if( p->tn.rval == 0x3000 ) { + printf("_%s(",p->in.name); + prnames(TINT,(int)p->tn.lval,0); + putchar(')'); + } else if( p->tn.lval == 0 ) { + if(p->tn.rval < 0 && *(p->in.name)=='L') + printf("%s",p->in.name); + else + printf( "_%s", p->in.name ); + } + else + { + if(p->tn.rval < 0 && *(p->in.name)=='L') + printf( "%s+%%%x", p->in.name , (unsigned short) p->tn.lval ); + else + printf( "_%s+%%%x", p->in.name , (unsigned short) p->tn.lval ); + } + if( p->tn.lval != 0 && (p->tn.rval == 0xa000 || p->tn.rval == 0x2000)) + printf( "+%%%x", (unsigned short) p->tn.lval ); +} +*/ +static char *ccbranches[] = +{ +/* + " beq L%%%d\n", + " bne L%%%d\n", + " ble L%%%d\n", + " blt L%%%d\n", + " bge L%%%d\n", + " bgt L%%%d\n", + " bls L%%%d\n", + " blo L%%%d\n", + " bhs L%%%d\n", + " bhi L%%%d\n", +*/ + " jpr eq,L%d\n", + " jpr ne,L%d\n", + " jpr le,L%d\n", + " jpr lt,L%d\n", + " jpr ge,L%d\n", + " jpr gt,L%d\n", + " jpr ule,L%d\n", + " jpr ult,L%d\n", + " jpr uge,L%d\n", + " jpr ugt,L%d\n", +}; + +cbgen( o, lab, mode ) +register o,lab; +{ + /* printf conditional and unconditional branches */ + if( o == 0 ) printf( " jpr L%d\n", lab ); + else if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); + else printf( ccbranches[o-EQ], lab ); +} + +static char *dbccops[] = +{ +/* + " dbeq %%d%d,L%%%d\n", + " dbne %%d%d,L%%%d\n", + " dble %%d%d,L%%%d\n", + " dblt %%d%d,L%%%d\n", + " dbge %%d%d,L%%%d\n", + " dbgt %%d%d,L%%%d\n", + " dbls %%d%d,L%%%d\n", + " dblo %%d%d,L%%%d\n", + " dbhs %%d%d,L%%%d\n", + " dbhi %%d%d,L%%%d\n", +*/ + "ne", "eq", "gt", "ge", "lt", "le", "ugt", "uge", "ult", "ule", +}; + +dbccgen( o, lab, reg ) +register o,reg,lab; +{ + /* printf conditional and unconditional branches */ + int l; +/* + if( o == 0 ) printf( " dbt %%d%d,L%%%d\n", reg, lab ); + else if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); + else printf( dbccops[o-EQ], reg, lab ); +*/ + if( o == 0) printf("\tdec\t%s\n\tjpr\tpl,L%d\n",prnames(TINT,reg,0),lab); + else if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); + else { + l = getlab(); + printf("\tjr\t%s,L%d\n\tdec\t%s\n\tjpr\tpl,L%d\nL%d:\n", + dbccops[o-EQ],l,prnames(TINT,reg,0),lab,l); + } +} + +/* see if an unused register can be used for a temp */ + +/*#define DREGS (0xff & (0xff< 1 reg or structures */ + mask = ~(regvar | regtmp); /* consider all unallocated registers */ + +/* if ((type & TPOINT) && (mask & AREGS)) */ +/* mask &= AREGS; /* prefer pointers in A registers */ +/* /* but can be put in D registers if no A's */ +/* else */ +/* mask &= DREGS; /* non-pointers restricted to D registers */ + mask &= MREGS; + + if (mask == 0) + return(0); /* none available! */ + + for (r = 8, rbit = 0x100; (mask & rbit) == 0; r++) + rbit <<= 1; + /* mark it used */ + regtmp |= rbit; + SETREGS(rbit); + *rnum = r; + return (1); /* success! */ + }