4.4BSD/usr/src/usr.bin/f77/pass1.tahoe/tahoe.c

Compare this file to the similar file:
Show the results in this format:

/*-
 * Copyright (c) 1980 The Regents of the University of California.
 * All rights reserved.
 *
 * This module is believed to contain source code proprietary to AT&T.
 * Use and redistribution is subject to the Berkeley Software License
 * Agreement and your Software Agreement with AT&T (Western Electric).
 */

#ifndef lint
static char sccsid[] = "@(#)tahoe.c	5.3 (Berkeley) 4/12/91";
#endif /* not lint */

#include "defs.h"

#ifdef SDB
#	include <a.out.h>
extern int types2[];
#	ifndef N_SO
#		include <stab.h>
#	endif
#endif

#include "pcc.h"

/*
	TAHOE - SPECIFIC ROUTINES
*/

int maxregvar = MAXREGVAR;
int regnum[] =  { 10, 9, 8, 7, 6 } ;

ftnint intcon[14] =
	{ 2, 2, 2, 2,
	  15, 31, 24, 56,
	  -128, -128, 127, 127,
	  0x7FFF, 0x7FFFFFFF };

#if HERE == VAX || HERE == TAHOE
	/* then put in constants in hex */
short realcon[6][4] =
	{
		{ 0x80, 0, 0, 0 },
		{ 0x80, 0, 0, 0 },
		{ 0x7FFF, 0xFFFF, 0, 0 },
		{ 0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF },
		{ 0x3480, 0, 0, 0 },
		{ 0x2480, 0, 0, 0 },
	};
#else
double realcon[6] =
	{
	2.9387358771e-39,		/* 2 ** -128 */
	2.938735877055718800e-39,	/* 2 ** -128 */
	1.7014117332e+38,		/* 2**127 * (1 - 2**-24) */
	1.701411834604692250e+38,	/* 2**127 * (1 - 2**-56) */
	5.960464e-8,			/* 2 ** -24 */
	1.38777878078144567e-17,	/* 2 ** -56 */
	};
#endif

/*
 * The VAX assembler has a serious and not easily fixable problem
 * with generating instructions that contain expressions of the form
 * label1-label2 where there are .align's in-between the labels.
 * Therefore, the compiler must keep track of the offsets and output
 * .space where needed.
 */
LOCAL int i_offset;		/* initfile offset */
LOCAL int a_offset;		/* asmfile offset */

prsave(proflab)
int proflab;
{
if(profileflag)
	{
	fprintf(asmfile, "\t.align\t2\n");
	fprintf(asmfile, "L%d:\t.long\t0\n", proflab);
	p2pi("\tpushl\t$L%d", proflab);
	p2pass("\tcallf\t$8,mcount");
	}
p2pi("\tsubl3\t$LF%d,fp,sp", procno);
}

goret(type)
int type;
{
register int r = 0;
switch(type) {	/* from retval */
	case TYDREAL:
		r++;

	case TYLOGICAL:
	case TYADDR:
	case TYSHORT:
	case TYLONG:
	case TYREAL:
		r++;

	case TYCHAR:
	case TYCOMPLEX:
	case TYDCOMPLEX:
		break;
	case TYSUBR:
		if (substars) r++;
		break;
	default:
		badtype("goret", type);
	}
p2pi("\tret#%d", r);
}

/*
 * move argument slot arg1 (relative to fp)
 * to slot arg2 (relative to ARGREG)
 */
mvarg(type, arg1, arg2)
int type, arg1, arg2;
{
p2pij("\tmovl\t%d(fp),%d(fp)", arg1+ARGOFFSET, arg2+argloc);
}

prlabel(fp, k)
FILEP fp;
int k;
{
fprintf(fp, "L%d:\n", k);
}

prconi(fp, type, n)
FILEP fp;
int type;
ftnint n;
{
register int i;

if(type == TYSHORT)
	{
	fprintf(fp, "\t.word\t%ld\n", n);
	i = SZSHORT;
	}
else
	{
	fprintf(fp, "\t.long\t%ld\n", n);
	i = SZLONG;
	}
if(fp == initfile)
	i_offset += i;
else
	a_offset += i;
}

prcona(fp, a)
FILEP fp;
ftnint a;
{
fprintf(fp, "\t.long\tL%ld\n", a);
if(fp == initfile)
	i_offset += SZLONG;
else
	a_offset += SZLONG;
}

prconr(fp, type, x)
FILEP fp;
int type;
double x;
{
/*
fprintf(fp, "\t%s\t0f%e\n", (type==TYREAL ? ".float" : ".double"), x);
*/
	/* non-portable cheat to preserve bit patterns */
	/* this code should be the same for PDP, VAX and Tahoe */

	register struct sh4 {
		unsigned short sh[4];
	} *cheat;
	register int i;

	cheat = (struct sh4 *)&x;
	if(type == TYREAL) {	/* force rounding */
		float f;
		f = x;
		x = f;
	}
	fprintf(fp, "	.long	0x%04x%04x", cheat->sh[0], cheat->sh[1]);
	if(type == TYDREAL) {
		fprintf(fp, ", 0x%04x%04x", cheat->sh[2], cheat->sh[3]);
		fprintf(fp, "	# .double %.17g\n", x);
		i = SZDOUBLE;
	} 
	else
	{
		fprintf(fp, "	# .float %.8g\n", x);
		i = SZFLOAT;
	}
if(fp == initfile)
	i_offset += i;
else
	a_offset += i;
}

praddr(fp, stg, varno, offset)
FILE *fp;
int stg, varno;
ftnint offset;
{
char *memname();

if(stg == STGNULL)
	fprintf(fp, "\t.long\t0\n");
else
	{
	fprintf(fp, "\t.long\t%s", memname(stg,varno));
	if(offset)
		fprintf(fp, "+%ld", offset);
	fprintf(fp, "\n");
	}
if(fp == initfile)
	i_offset += SZADDR;
else
	a_offset += SZADDR;
}
pralign(k)
int k;
{
  register int lg;

  if (k > 4)
    lg = 3;
  else if (k > 2)
    lg = 2;
  else if (k > 1)
    lg = 1;
  else
    return;
  fprintf(initfile, "\t.align\t%d\n", lg);
i_offset += lg;
  return;
}



prspace(n)
int n;
{

fprintf(initfile, "\t.space\t%d\n", n);
i_offset += n;
}


preven(k)
int k;
{
register int lg;

if(k > 4)
	lg = 3;
else if(k > 2)
	lg = 2;
else if(k > 1)
	lg = 1;
else
	return;
fprintf(asmfile, "\t.align\t%d\n", lg);
a_offset += lg;
}

praspace(n)
int n;
{

fprintf(asmfile, "\t.space\t%d\n", n);
a_offset += n;
}


casegoto(index, nlab, labs)
expptr index;
register int nlab;
struct Labelblock *labs[];
{
register int i;
register int arrlab;

putforce(TYINT, index);
p2pi("\tcasel\tr0,$1,$%d\n\t.align 1", nlab-1);
p2pi("L%d:", arrlab = newlabel() );
for(i = 0; i< nlab ; ++i)
	if( labs[i] )
		p2pij("\t.word\tL%d-L%d", labs[i]->labelno, arrlab);
}


prarif(p, neg, zer, pos)
expptr p;
int neg, zer, pos;
{
putforce(p->headblock.vtype, p);
p2pass("\ttstl\tr0");
p2pi("\tjlss\tL%d", neg);
p2pi("\tjeql\tL%d", zer);
p2pi("\tjbr\tL%d", pos);
}

char *memname(stg, mem)
int stg, mem;
{
static char s[20];

switch(stg)
	{
	case STGEXT:
	case STGINTR:
		if(extsymtab[mem].extname[0] == '@') {	/* function opcodes */
			strcpy(s, varstr(XL, extsymtab[mem].extname));
			break;
		}
	case STGCOMMON:
		sprintf(s, "_%s", varstr(XL, extsymtab[mem].extname) );
		break;

	case STGBSS:
	case STGINIT:
		sprintf(s, "v.%d", mem);
		break;

	case STGCONST:
		sprintf(s, "L%d", mem);
		break;

	case STGEQUIV:
		sprintf(s, "q.%d", mem+eqvstart);
		break;

	default:
		badstg("memname", stg);
	}
return(s);
}

prlocvar(s, len)
char *s;
ftnint len;
{
int sz;
sz = len;
if (sz % SZINT)
	sz += SZINT - (sz % SZINT);
fprintf(asmfile, "\t.lcomm\t%s,%ld\n", s, sz);
}

char *
packbytes(cp)
register Constp cp;
{
#if HERE == VAX
  static char shrt[16];
  static char lng[4];
#endif

  switch (cp->vtype)
    {
#if HERE == TAHOE
    case TYSHORT:
    { static short shrt;
      shrt = cp->constant.ci;
      return ((char *)&shrt);
    }
    case TYLONG:
    case TYLOGICAL:
    case TYREAL:
    case TYDREAL:
    case TYDCOMPLEX:
      return ((char *)&cp->constant);
    case TYCOMPLEX:
      { static float quad[2];
      quad[0] = cp->constant.cd[0];
      quad[1] = cp->constant.cd[1];
      return ((char *)quad);
      }
#endif

#if HERE == VAX
    case TYLONG:
    case TYLOGICAL:
      swab4((char *)&cp->constant.ci, lng, 4);
      return (lng);

    case TYSHORT:
    case TYREAL:
    case TYDREAL:
    case TYDCOMPLEX:
      swab((char *)cp->constant.cd, shrt, typesize[cp->vtype]);
      return (shrt);
    case TYCOMPLEX:
      swab((char *)cp->constant.cd, shrt, 4);
      swab((char *)&(cp->constant.cd[1]), &shrt[4], 4);
      return (shrt);
#endif

    default:
      badtype("packbytes", cp->vtype);
    }
}

#if HERE == VAX
/* correct the byte order in longs */
LOCAL swab4(from, to, n)
  register char *to, *from;
  register int n;
{
  while(n >= 4) {
    *to++ = from[3];
    *to++ = from[2];
    *to++ = from[1];
    *to++ = from[0];
    from += 4;
    n -= 4;
  }
  while(n >= 2) {
    *to++ = from[1];
    *to++ = from[0];
    from += 2;
    n -= 2;
  }
  if(n > 0)
	*to = *from;
}
#endif

prsdata(s, len)
register char *s; /* must be aligned if HERE==TAHOE */
register int len;
{
  static char longfmt[] = "\t.long\t0x%x\n";
  static char wordfmt[] = "\t.word\t0x%x\n";
  static char bytefmt[] = "\t.byte\t0x%x\n";

  register int i;
#if HERE == VAX
  char quad[8];
  swab4(s, quad, len);
  s = quad;
#endif

  i = 0;
  if ((len - i) >= 4)
    {
      fprintf(initfile, longfmt, *((int *) s));
      i += 4;
    }
  if ((len - i) >= 2)
    {
      fprintf(initfile, wordfmt, 0xffff & (*((short *) (s + i))));
      i += 2;
    }
  if ((len - i) > 0)
    fprintf(initfile,bytefmt, 0xff & s[i]);

  i_offset += len;
  return;
}

prquad(s)
register long *s;
{
  static char quadfmt1[] = "\t.quad\t0x%x\n";
  static char quadfmt2[] = "\t.quad\t0x%x%08x\n";
#if HERE == VAX
  char quad[8];
  swab4((char *)s, quad, 8);
  s = (long *)quad;
#endif

  if (s[0] == 0 )
    fprintf(initfile, quadfmt1, s[1]);
  else
    fprintf(initfile, quadfmt2, s[0], s[1]);

  return;
}

#ifdef UCBVAXASM
prfill(n, s)
int n;
register long *s;
{
  static char fillfmt1[] = "\t.fill\t%d,8,0x%x\n";
  static char fillfmt2[] = "\t.fill\t%d,8,0x%x%08x\n";
#if HERE == VAX
  char quad[8];
  swab4((char *)s, quad, 8);
  s = (long *)quad;
#endif

  if (s[0] == 0 )
    fprintf(initfile, fillfmt1, n, s[1]);
  else
    fprintf(initfile, fillfmt2, n, s[0], s[1]);

  return;
}
#endif

prext(ep)
register struct Extsym *ep;
{
  static char globlfmt[] = "\t.globl\t_%s\n";
  static char commfmt[] = "\t.comm\t_%s,%ld\n";
  static char align2fmt[] = "\t.align\t2\n";
  static char labelfmt[] = "_%s:\n";

  static char seekerror[] = "seek error on tmp file";
  static char readerror[] = "read error on tmp file";

  char *tag;
  register int leng;
  long pos;
  register char *p;
  long oldvalue[2];
  long newvalue[2];
  register int n;
  register int repl;

  tag = varstr(XL, ep->extname);
  leng = ep->maxleng;

  if (leng == 0)
    {
      if(*tag != '@')	/* function opcodes */
      fprintf(asmfile, globlfmt, tag);
      return;
    }

  if (ep->init == NO)
    {
      fprintf(asmfile, commfmt, tag, leng);
      return;
    }

  fprintf(asmfile, globlfmt, tag);
  fprintf(initfile, align2fmt);
  fprintf(initfile, labelfmt, tag);

  pos = lseek(cdatafile, ep->initoffset, 0);
  if (pos == -1)
    {
      err(seekerror);
      done(1);
    }

  oldvalue[0] = 0;
  oldvalue[1] = 0;
  n = read(cdatafile, oldvalue, 8);
  if (n < 0)
    {
      err(readerror);
      done(1);
    }

  if (leng <= 8)
    {
      p = (char *)oldvalue + leng;
      while (p > (char *)oldvalue && *--p == '\0') /* SKIP */;
      if (*p == '\0')
	prspace(leng);
      else if (leng == 8)
	prquad(oldvalue);
      else
	prsdata(oldvalue, leng);

      return;
    }

  repl = 1;
  leng -= 8;

  while (leng >= 8)
    {
      newvalue[0] = 0;
      newvalue[1] = 0;

      n = read(cdatafile, newvalue, 8);
      if (n < 0)
	{
	  err(readerror);
	  done(1);
	}

      leng -= 8;

      if (oldvalue[0] == newvalue[0]
	  && oldvalue[1] == newvalue[1])
	repl++;
      else
	{
	  if (oldvalue[0] == 0
	      && oldvalue[1] == 0)
	    prspace(8*repl);
	  else if (repl == 1)
	    prquad(oldvalue);
	  else
#ifdef UCBVAXASM
	    prfill(repl, oldvalue);
#else
	    {
	      while (repl-- > 0)
		prquad(oldvalue);
	    }
#endif
	  oldvalue[0] = newvalue[0];
	  oldvalue[1] = newvalue[1];
	  repl = 1;
	}
    }

  newvalue[0] = 0;
  newvalue[1] = 0;

  if (leng > 0)
    {
      n = read(cdatafile, newvalue, leng);
      if (n < 0)
	{
	  err(readerror);
	  done(1);
	}
    }

  if (oldvalue[1] == 0
      && oldvalue[0] == 0
      && newvalue[1] == 0
      && newvalue[0] == 0)
    {
      prspace(8*repl + leng);
      return;
    }

  if (oldvalue[1] == 0
      && oldvalue[0] == 0)
    prspace(8*repl);
  else if (repl == 1)
    prquad(oldvalue);
  else
#ifdef UCBVAXASM
    prfill(repl, oldvalue);
#else
    {
      while (repl-- > 0)
	prquad(oldvalue);
    }
#endif

  prsdata(newvalue, leng);

  return;
}

prlocdata(sname, leng, type, initoffset, inlcomm)
char *sname;
ftnint leng;
int type;
long initoffset;
char *inlcomm;
{
  static char seekerror[] = "seek error on tmp file";
  static char readerror[] = "read error on tmp file";

  static char labelfmt[] = "%s:\n";

  register int k;
  register char *p;
  register int repl;
  register int first;
  register long pos;
  register long n;
  long oldvalue[2];
  long newvalue[2];

  *inlcomm = NO;

  k = leng;
  first = YES;

  pos = lseek(vdatafile, initoffset, 0);
  if (pos == -1)
    {
      err(seekerror);
      done(1);
    }

  oldvalue[0] = 0;
  oldvalue[1] = 0;
  n = read(vdatafile, oldvalue, 8);
  if (n < 0)
    {
      err(readerror);
      done(1);
    }

  if (k <= 8)
    {
      p = (char *)oldvalue + k;
      while (p > (char *)oldvalue && *--p == '\0')
	/*  SKIP  */ ;
      if (*p == '\0')
	{
	  if (SMALLVAR(leng))
	    {
	      pralign(typealign[type]);
	      fprintf(initfile, labelfmt, sname);
	      prspace(leng);
	    }
	  else
	    {
	      preven(ALIDOUBLE);
	      prlocvar(sname, leng);
	      *inlcomm = YES;
	    }
	}
      else
	{
	  fprintf(initfile, labelfmt, sname);
	  if (leng == 8)
	    prquad(oldvalue);
	  else
	    prsdata(oldvalue, leng);
	}
      return;
    }

  repl = 1;
  k -= 8;

  while (k >=8)
    {
      newvalue[0] = 0;
      newvalue[1] = 0;

      n = read(vdatafile, newvalue, 8);
      if (n < 0)
	{
	  err(readerror);
	  done(1);
	}

      k -= 8;

      if (oldvalue[0] == newvalue[0]
	  && oldvalue[1] == newvalue[1])
	repl++;
      else
	{
	  if (first == YES)
	    {
	      pralign(typealign[type]);
	      fprintf(initfile, labelfmt, sname);
	      first = NO;
	    }

	  if (oldvalue[0] == 0
	      && oldvalue[1] == 0)
	    prspace(8*repl);
	  else
	    {
	      while (repl-- > 0)
		prquad(oldvalue);
	    }
	  oldvalue[0] = newvalue[0];
	  oldvalue[1] = newvalue[1];
	  repl = 1;
	}
    }

  newvalue[0] = 0;
  newvalue[1] = 0;

  if (k > 0)
    {
      n = read(vdatafile, newvalue, k);
      if (n < 0)
	{
	  err(readerror);
	  done(1);
	}
    }

  if (oldvalue[1] == 0
      && oldvalue[0] == 0
      && newvalue[1] == 0
      && newvalue[0] == 0)
    {
      if (first == YES && !SMALLVAR(leng))
	{
	  prlocvar(sname, leng);
	  *inlcomm = YES;
	}
      else
	{
	  if (first == YES)
	    {
	      pralign(typealign[type]);
	      fprintf(initfile, labelfmt, sname);
	    }
	  prspace(8*repl + k);
	}
      return;
    }

  if (first == YES)	
    {
      pralign(typealign[type]);
      fprintf(initfile, labelfmt, sname);
    }

  if (oldvalue[1] == 0
      && oldvalue[0] == 0)
    	prspace(8*repl);
  else
    {
      while (repl-- > 0)
	prquad(oldvalue);
    }

  prsdata(newvalue, k);

  return;
}

prendproc()
{
}

prtail()
{
}

prolog(ep, argvec)
struct Entrypoint *ep;
Addrp  argvec;
{
int i, argslot, proflab;
int size;
register chainp p;
register Namep q;
register struct Dimblock *dp;
expptr tp;
static char maskfmt[] = "\t.word\tLWM%d";
static char align1fmt[] = "\t.align\t1";

if(procclass == CLMAIN) {
	if(fudgelabel)
		{
		if(ep->entryname) {
			p2pass(align1fmt);
			p2ps("_%s:",  varstr(XL, ep->entryname->extname));
			p2pi(maskfmt, procno);
		}
		putlabel(fudgelabel);
		fudgelabel = 0;
		}
	else
		{
		p2pass(align1fmt);
		p2pass( "_MAIN_:" );
		if(ep->entryname == NULL)
			p2pi(maskfmt, procno);
		}

} else if(ep->entryname)
	if(fudgelabel)
		{
		putlabel(fudgelabel);
		fudgelabel = 0;
		}
	else
		{
		p2pass(align1fmt);
		p2ps("_%s:",  varstr(XL, ep->entryname->extname));
		p2pi(maskfmt, procno);
		prsave(newlabel());
		}

if(procclass == CLBLOCK)
	return;
if (anylocals == YES)
	p2pi("\tmovl\t$v.%d,r11", bsslabel);
if(argvec)
	{
	if (argvec->tag != TADDR) badtag ("prolog",argvec->tag);
	argloc = argvec->memoffset->constblock.constant.ci + SZINT;
			/* first slot holds count */
	if(proctype == TYCHAR)
		{
		mvarg(TYADDR, 0, chslot);
		mvarg(TYLENG, SZADDR, chlgslot);
		argslot = SZADDR + SZLENG;
		}
	else if( ISCOMPLEX(proctype) )
		{
		mvarg(TYADDR, 0, cxslot);
		argslot = SZADDR;
		}
	else
		argslot = 0;

	for(p = ep->arglist ; p ; p =p->nextp)
		{
		q = (Namep) (p->datap);
		mvarg(TYADDR, argslot, q->vardesc.varno);
		argslot += SZADDR;
		}
	for(p = ep->arglist ; p ; p = p->nextp)
		{
		q = (Namep) (p->datap);
		if(q->vtype==TYCHAR && q->vclass!=CLPROC)
			{
			if(q->vleng && ! ISCONST(q->vleng) )
				mvarg(TYLENG, argslot,
					q->vleng->addrblock.memno);
			argslot += SZLENG;
			}
		}
	if ((ep->enamep->vtype == TYCOMPLEX) && (!ep->arglist))
		p2pass("\tmovl\tfp,r12");
	else
		p2pi("\tsubl3\t$%d,fp,r12", ARGOFFSET-argloc);
	} else 
	if((ep->arglist) || (ISCOMPLEX(proctype)) || (proctype == TYCHAR))
		p2pass("\tmovl\tfp,r12");

for(p = ep->arglist ; p ; p = p->nextp)
	{
	q = (Namep) (p->datap);
	if(dp = q->vdim)
		{
		for(i = 0 ; i < dp->ndim ; ++i)
			if(dp->dims[i].dimexpr)
				puteq( fixtype(cpexpr(dp->dims[i].dimsize)),
					fixtype(cpexpr(dp->dims[i].dimexpr)));
#ifdef SDB
                if(sdbflag) {
		for(i = 0 ; i < dp->ndim ; ++i) {
			if(dp->dims[i].lbaddr)
				puteq( fixtype(cpexpr(dp->dims[i].lbaddr)),
					fixtype(cpexpr(dp->dims[i].lb)));
			if(dp->dims[i].ubaddr)
				puteq( fixtype(cpexpr(dp->dims[i].ubaddr)),
					fixtype(cpexpr(dp->dims[i].ub)));
		    
                                                }
                            }
#endif
		size = typesize[ q->vtype ];
		if(q->vtype == TYCHAR)
			if( ISICON(q->vleng) )
				size *= q->vleng->constblock.constant.ci;
			else
				size = -1;

		/* on TAHOE, get more efficient subscripting if subscripts
		   have zero-base, so fudge the argument pointers for arrays.
		   Not done if array bounds are being checked.
		*/
		if(dp->basexpr)
			puteq( 	cpexpr(fixtype(dp->baseoffset)),
				cpexpr(fixtype(dp->basexpr)));
#ifdef SDB
		if( (! checksubs) && (! sdbflag) )
#else
		if(! checksubs)
#endif
			{
			if(dp->basexpr)
				{
				if(size > 0)
					tp = (expptr) ICON(size);
				else
					tp = (expptr) cpexpr(q->vleng);
				putforce(TYINT,
					fixtype( mkexpr(OPSTAR, tp,
						cpexpr(dp->baseoffset)) ));
				p2pi("\tsubl2\tr0,%d(r12)",
					p->datap->nameblock.vardesc.varno +
						ARGOFFSET);
				}
			else if(dp->baseoffset->constblock.constant.ci != 0)
				{
				if(size > 0)
					{
					p2pij("\tsubl2\t$%ld,%d(r12)",
						dp->baseoffset->constblock.constant.ci * size,
						p->datap->nameblock.vardesc.varno +
							ARGOFFSET);
					}
				else	{
					putforce(TYINT, mkexpr(OPSTAR, cpexpr(dp->baseoffset),
						cpexpr(q->vleng) ));
					p2pi("\tsubl2\tr0,%d(r12)",
						p->datap->nameblock.vardesc.varno +
							ARGOFFSET);
					}
				}
			}
		}
	}

if(typeaddr)
	puteq( cpexpr(typeaddr), mkaddcon(ep->typelabel) );
/* replace to avoid long jump problem
putgoto(ep->entrylabel);
*/
p2pi("\tjbr\tL%d", ep->entrylabel);
}

prhead(fp)
FILEP fp;
{
#if FAMILY==PCC
	p2triple(PCCF_FLBRAC, ARGREG-highregvar, procno);
	p2word( (long) (BITSPERCHAR*autoleng) );
	p2flush();
#endif
}