#include "defs"

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

#include "pccdefs"

/*
	PDP11-780/VAX - SPECIFIC ROUTINES
*/


int maxregvar = MAXREGVAR;
int regnum[] =  { 11, 10, 9, 8, 7, 6 } ;
static int regmask[] = { 0, 0x800, 0xc00, 0xe00, 0xf00, 0xf80, 0xfc0 };



ftnint intcon[14] =
	{ 2, 2, 2, 2,
	  15, 31, 24, 56,
	  -128, -128, 127, 127,
	  32767, 2147483647 };

#if HERE == VAX
	/* then put in constants in octal */
long realcon[6][2] =
	{
		{ 0200, 0 },
		{ 0200, 0 },
		{ 037777677777, 0 },
		{ 037777677777, 037777777777 },
		{ 032200, 0 },
		{ 022200, 0 }
	};
#else
double realcon[6] =
	{
	2.9387358771e-39,
	2.938735877055718800e-39
	1.7014117332e+38,
	1.701411834604692250e+38
	5.960464e-8,
	1.38777878078144567e-17,
	};
#endif




prsave()
{
int proflab;
p2pi("\t.word\t0x%x", regmask[highregvar]);	/*  register variable mask */
if(profileflag)
	{
	proflab = newlabel();
	fprintf(asmfile, "L%d:\t.space\t4\n", proflab);
	p2pi("\tmovab\tL%d,r0", proflab);
	p2pass("\tjsb\tmcount");
	}
p2pi("\tsubl2\t$.F%d,sp", procno);
}



goret(type)
int type;
{
p2pass("\tret");
}




/*
 * move argument slot arg1 (relative to ap)
 * to slot arg2 (relative to ARGREG)
 */

mvarg(type, arg1, arg2)
int type, arg1, arg2;
{
p2pij("\tmovl\t%d(ap),%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;
{
fprintf(fp, "\t%s\t%ld\n", (type==TYSHORT ? ".word" : ".long"), n);
}



prcona(fp, a)
FILEP fp;
ftnint a;
{
fprintf(fp, "\t.long\tL%ld\n", a);
}



#ifndef vax
prconr(fp, type, x)
FILEP fp;
int type;
float x;
{
fprintf(fp, "\t%s\t0f%e\n", (type==TYREAL ? ".float" : ".double"), x);
}
#endif

#ifdef vax
prconr(fp, type, x)
FILEP fp;
int type;
double x;
{
long int *n;
n = &x;	/* nonportable cheat */
if(type == TYREAL)
	fprintf(fp, "\t.long\t0x%X\n", n[0]);
else
	fprintf(fp, "\t.long\t0x%X,0x%X\n", n[0], n[1]);
}
#endif







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);
}



vaxgoto(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", 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);
if( ISINT(p->headblock.vtype) )
	p2pass("\ttstl\tr0");
else
	p2pass("\ttstd\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 STGCOMMON:
	case STGEXT:
		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:
		fatali("memname: invalid vstg %d", stg);
	}
return(s);
}




prlocvar(s, len)
char *s;
ftnint len;
{
fprintf(asmfile, "\t.lcomm\t%s,%ld\n", s, len);
}



prext(name, leng, init)
char *name;
ftnint leng;
int init;
{
if(leng == 0)
	fprintf(asmfile, "\t.globl\t_%s\n", name);
else
	fprintf(asmfile, "\t.comm\t_%s,%ld\n", name, leng);
}





prendproc()
{
}




prtail()
{
}





prolog(ep, argvec)
struct Entrypoint *ep;
struct Addrblock *argvec;
{
int i, argslot, proflab;
int size;
register chainp p;
register struct Nameblock *q;
register struct Dimblock *dp;
expptr tp;

if(procclass == CLMAIN)
	p2pass( "_MAIN__:" );
if(ep->entryname)
	p2ps("_%s:",  varstr(XL, ep->entryname->extname));
if(procclass == CLBLOCK)
	return;
prsave();
if(argvec)
	{
	argloc = argvec->memoffset->constblock.const.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 = p->datap;
		mvarg(TYADDR, argslot, q->vardesc.varno);
		argslot += SZADDR;
		}
	for(p = ep->arglist ; p ; p = p->nextp)
		{
		q = p->datap;
		if(q->vtype==TYCHAR || q->vclass==CLPROC)
			{
			if(q->vleng && q->vleng->headblock.tag!=TCONST)
				mvarg(TYLENG, argslot,
					q->vleng->nameblock.vardesc.varno);
			argslot += SZLENG;
			}
		}
	p2pi("\taddl3\t$%d,fp,ap", argloc-ARGOFFSET);
	p2pi("\tmovl\t$%d,(ap)\n", lastargslot/SZADDR);
	}

for(p = ep->arglist ; p ; p = p->nextp)
	{
	q = 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)));
		size = typesize[ q->vtype ];
		if(q->vtype == TYCHAR)
			if( ISICON(q->vleng) )
				size *= q->vleng->constblock.const.ci;
			else
				size = -1;

		/* on VAX, 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)));

		if(! checksubs)
			{
			if(dp->basexpr)
				{
				if(size > 0)
					tp = ICON(size);
				else
					tp = cpexpr(q->vleng);
				putforce(TYINT,
					fixtype( mkexpr(OPSTAR, tp,
						cpexpr(dp->baseoffset)) ));
				p2pi("\tsubl2\tr0,%d(ap)",
					p->datap->nameblock.vardesc.varno +
						ARGOFFSET);
				}
			else if(dp->baseoffset->constblock.const.ci != 0)
				{
				char buff[25];
				if(size > 0)
					{
					sprintf(buff, "\tsubl2\t$%ld,%d(ap)",
						dp->baseoffset->constblock.const.ci * size,
						p->datap->nameblock.vardesc.varno +
							ARGOFFSET);
					}
				else	{
					putforce(TYINT, mkexpr(OPSTAR, cpexpr(dp->baseoffset),
						cpexpr(q->vleng) ));
					sprintf(buff, "\tsubl2\tr0,%d(ap)",
						p->datap->nameblock.vardesc.varno +
							ARGOFFSET);
					}
				p2pass(buff);
				}
			}
		}
	}

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




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



prdbginfo()
{
}

#ifdef SDB


#	ifdef UCBVAXASM
	char *stabdline(code, type)
	int code;
	int type;
	{
	static char buff[30];

	sprintf(buff, "\t.stabd\t0%o,0,0%o\n", code, type);
	return(buff);
	}
#	endif


prstab(s, code, type, loc)
char *s, *loc;
int code, type;
{
char * stabline();

if(sdbflag)
	fprintf(asmfile, stabline(s,code,type,loc) );
}



char *stabline(s, code, type, loc)
register char *s;
int code;
int type;
char *loc;
{
static char buff[50]	= "\t.stab\t\t";
register char *t;
register int i = 0;

#ifdef UCBVAXASM
t = buff + 8;
if(s == NULL)
	buff[6] = 'n';	/* .stabn line */
else
	{
	buff[6] = 's';  /* .stabs line */
	*t++ = '"';
	while(*s!='\0' && *s!=' ' && i<8)
		{
		*t++ = *s++;
		++i;
		}
	*t++ = '"';
	*t++ = ',';
	}

#else
	t = buff + 7;
	if(s)
		while( *s!='\0' && *s!=' ' && i<8 )
			{
			*t++ = '\'';
			*t++ = *s++;
			*t++ = ',';
			++i;
			}
	for( ; i<8 ; ++i)
		{
		*t++ = '0';
		*t++ = ',';
		}
#endif


sprintf(t, "0%o,0,0%o,%s\n", code,  type, (loc? loc : "0") );
return(buff);
}



prstleng(np, leng)
register struct Nameblock *np;
ftnint leng;
{
ftnint iarrlen();

prstab( varstr(XL,np->varname), N_LENG, 0, convic(leng) );
}



stabtype(p)
register struct Nameblock *p;
{
register int type;
register int shift;
type = types2[p->vtype];
if(p->vdim)
	{
	type |= 060;	/* .stab code for array */
	shift = 2;
	}
else if(p->vclass == CLPROC)
	{
	type |= 040;	/* .stab code for function */
	shift = 2;
	}
else
	shift = 0;

if(p->vstg == STGARG)
	type |= (020 << shift);	/* code for pointer-to */

return(type);
}




prstssym(np)
register struct Nameblock *np;
{
prstab(varstr(VL,np->varname), N_SSYM,
	stabtype(np), convic(np->voffset) );
}
#endif
