local2.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,374 行 · 第 1/2 页

C
1,374
字号
#ifndef lintstatic char	*sccsid = " @(#)local2.c	1.2	(ULTRIX)	1/16/86";#endif lint/************************************************************************ *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//**************************************************************************			Modification History**	David Metsky		14-Jan-86** 001	Replaced old version with BSD 4.3 version as part of upgrade.**	Based on:	local2.c	1.12		8/23/85**************************************************************************/# include "pass2.h"# include "ctype.h"# ifdef FORTint ftlab1, ftlab2;# endif/* a lot of the machine dependent parts of the second pass */# define putstr(s)	fputs((s), stdout)# define BITMASK(n) ((1L<<n)-1)where(c){	fprintf( stderr, "%s, line %d: ", filename, lineno );	}lineid( l, fn ) char *fn; {	/* identify line l and file fn */	printf( "#	line %d, file %s\n", l, fn );	}eobl2(){	OFFSZ spoff;	/* offset from stack pointer */#ifdef FORT	spoff = maxoff;	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;	spoff /= SZCHAR;	SETOFF(spoff,4);#ifndef FLEXNAMES	printf( "	.set	.F%d,%ld\n", ftnno, spoff );#else	/* SHOULD BE L%d ... ftnno but must change pc/f77 */	printf( "	.set	LF%d,%ld\n", ftnno, spoff );#endif#else	extern int ftlab1, ftlab2;	spoff = maxoff;	if( spoff >= AUTOINIT ) spoff -= AUTOINIT;	spoff /= SZCHAR;	SETOFF(spoff,4);	printf( "L%d:\n", ftlab1);	if( spoff!=0 )		if( spoff < 64 )			printf( "	subl2	$%ld,sp\n", spoff);		else			printf( "	movab	-%ld(sp),sp\n", spoff);	printf( "	jbr 	L%d\n", ftlab2);#endif	maxargs = -1;	}struct hoptab { int opmask; char * opstring; } ioptab[] = {	ASG PLUS, "add",	ASG MINUS, "sub",	ASG MUL, "mul",	ASG DIV, "div",	ASG OR, "bis",	ASG ER,	"xor",	ASG AND, "bic",	PLUS,	"add",	MINUS,	"sub",	MUL,	"mul",	DIV,	"div",	OR,	"bis",	ER,	"xor",	AND,	"bic",	-1, ""    };hopcode( f, o ){	/* output the appropriate string from the above table */	register struct hoptab *q;	for( q = ioptab;  q->opmask>=0; ++q ){		if( q->opmask == o ){			putstr( q->opstring );/* tbl			if( f == 'F' ) putchar( 'e' );			else if( f == 'D' ) putchar( 'd' );   tbl *//* tbl */			switch( f ) {				case 'L':				case 'W':				case 'B':				case 'D':				case 'F':					putchar(tolower(f));					break;				}/* tbl */			return;			}		}	cerror( "no hoptab for %s", opst[o] );	}char *rnames[] = {  /* keyed to register number tokens */	"r0", "r1",	"r2", "r3", "r4", "r5",	"r6", "r7", "r8", "r9", "r10", "r11",	"ap", "fp", "sp", "pc",	};int rstatus[] = {	SAREG|STAREG, SAREG|STAREG,	SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,	SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,	SAREG, SAREG, SAREG, SAREG,	};tlen(p) NODE *p;{	switch(p->in.type) {		case CHAR:		case UCHAR:			return(1);		case SHORT:		case USHORT:			return(2);		case DOUBLE:			return(8);		default:			return(4);		}}mixtypes(p, q) NODE *p, *q;{	register TWORD tp, tq;	tp = p->in.type;	tq = q->in.type;	return( (tp==FLOAT || tp==DOUBLE) !=		(tq==FLOAT || tq==DOUBLE) );}prtype(n) NODE *n;{	switch (n->in.type)		{		case DOUBLE:			putchar('d');			return;		case FLOAT:			putchar('f');			return;		case LONG:		case ULONG:		case INT:		case UNSIGNED:			putchar('l');			return;		case SHORT:		case USHORT:			putchar('w');			return;		case CHAR:		case UCHAR:			putchar('b');			return;		default:			if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");			else {				putchar('l');				return;				}		}}zzzcode( p, c ) register NODE *p; {	register m;	CONSZ val;	switch( c ){	case 'N':  /* logical ops, turned into 0-1 */		/* use register given by register 1 */		cbgen( 0, m=getlab(), 'I' );		deflab( p->bn.label );		printf( "	clrl	%s\n", rnames[getlr( p, '1' )->tn.rval] );		deflab( m );		return;	case 'I':	case 'P':		cbgen( p->in.op, p->bn.label, c );		return;	case 'A':		{		register NODE *l, *r;		if (xdebug) eprint(p, 0, &val, &val);		r = getlr(p, 'R');		if (p->in.op == ASSIGN) {			l = getlr(p, 'L');			if (l->in.op == REG && l->in.type == SHORT &&			    r->in.op == ICON) {				l->in.type = INT;			      }		      }		else if (p->in.op == SCONV) {			l = resc;#if defined(FORT) || defined(SPRECC)			l->in.type = r->in.type;#else			l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type;#endif			r = getlr(p, 'L');			}		else {		/* OPLTYPE */			l = resc;#if defined(FORT) || defined(SPRECC)			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);#else			l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);#endif			}		if (r->in.op == ICON)			if (r->in.name[0] == '\0') {				if (r->tn.lval == 0) {					putstr("clr");					prtype(l);					putchar('\t');					adrput(l);					return;					}				if (r->tn.lval < 0 && r->tn.lval >= -63) {					putstr("mneg");					prtype(l);					r->tn.lval = -r->tn.lval;					goto ops;					}				if (r->tn.lval < 0)					r->in.type = r->tn.lval >= -128 ? CHAR						: (r->tn.lval >= -32768 ? SHORT						: INT);				else if (l->in.type == FLOAT ||				    l->in.type == DOUBLE)					r->in.type = r->tn.lval <= 63 ? INT						: (r->tn.lval <= 127 ? CHAR						: (r->tn.lval <= 32767 ? SHORT						: INT));				else					r->in.type = r->tn.lval <= 63 ? INT						: (r->tn.lval <= 127 ? CHAR						: (r->tn.lval <= 255 ? UCHAR						: (r->tn.lval <= 32767 ? SHORT						: (r->tn.lval <= 65535 ? USHORT						: INT))));				}			else {				putstr("moval");				putchar('\t');				acon(r);				putchar(',');				adrput(l);				return;				}		if (p->in.op == SCONV &&		    !(l->in.type == FLOAT || l->in.type == DOUBLE) &&		    !mixtypes(l, r)) {			/*			 * Because registers must always contain objects			 * of the same width as INTs, we may have to			 * perform two conversions to get an INT.  Can			 * the conversions be collapsed into one?			 */			if (m = collapsible(l, r))				r->in.type = m;			else {				/*				 * Two steps are required.				 */				NODE *x = &resc[1];				*x = *l;				if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))					putstr("movz");				else					putstr("cvt");				prtype(r);				prtype(x);				putchar('\t');				adrput(r);				putchar(',');				adrput(x);				putchar('\n');				putchar('\t');				r = x;				}			l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);			}		if (!mixtypes(l,r)) {			if (tlen(l) == tlen(r)) {				putstr("mov");#ifdef FORT				if (Oflag)					prtype(l);				else {					if (l->in.type == DOUBLE)						putchar('q');					else if(l->in.type == FLOAT)						putchar('l');					else						prtype(l);					}#else				prtype(l);#endif FORT				goto ops;				}			else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))				putstr("movz");			else				putstr("cvt");			}		else			putstr("cvt");		prtype(r);		prtype(l);	ops:		putchar('\t');		adrput(r);		putchar(',');		adrput(l);		return;		}	case 'B':	/* get oreg value in temp register for left shift */		{		register NODE *r;		if (xdebug) eprint(p, 0, &val, &val);		r = p->in.right;		if( tlen(r) == sizeof(int) && r->in.type != FLOAT )			putstr("movl");		else {			putstr("cvt");			prtype(r);			putchar('l');			}		return;		}	case 'C':	/* num words pushed on arg stack */		{		extern int gc_numbytes;		extern int xdebug;		if (xdebug) printf("->%d<-",gc_numbytes);		printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );		return;		}	case 'D':	/* INCR and DECR */		zzzcode(p->in.left, 'A');		putchar('\n');		putchar('\t');	case 'E':	/* INCR and DECR, FOREFF */		if (p->in.right->tn.lval == 1)			{			putstr( p->in.op == INCR ? "inc" : "dec" );			prtype(p->in.left);			putchar('\t');			adrput(p->in.left);			return;			}		putstr( p->in.op == INCR ? "add" : "sub" );		prtype(p->in.left);		putchar('2');		putchar('\t');		adrput(p->in.right);		putchar(',');		adrput(p->in.left);		return;	case 'F':	/* register type of right operand */		{		register NODE *n;		extern int xdebug;		register int ty;		n = getlr( p, 'R' );		ty = n->in.type;		if (xdebug) printf("->%d<-", ty);		if ( ty==DOUBLE) putchar('d');		else if ( ty==FLOAT ) putchar('f');		else putchar('l');		return;		}	case 'L':	/* type of left operand */	case 'R':	/* type of right operand */		{		register NODE *n;		extern int xdebug;		n = getlr( p, c );		if (xdebug) printf("->%d<-", n->in.type);		prtype(n);		return;		}	case 'Z':	/* complement mask for bit instr */		printf("$%ld", ~p->in.right->tn.lval);		return;	case 'U':	/* 32 - n, for unsigned right shifts */		printf("$%d", 32 - p->in.right->tn.lval );		return;	case 'T':	/* rounded structure length for arguments */		{		int size;		size = p->stn.stsize;		SETOFF( size, 4);		printf("$%d", size);		return;		}	case 'S':  /* structure assignment */		{			register NODE *l, *r;			register size;			if( p->in.op == STASG ){				l = p->in.left;				r = p->in.right;				}			else if( p->in.op == STARG ){  /* store an arg into a temporary */				r = p->in.left;				}			else cerror( "STASG bad" );			if( r->in.op == ICON ) r->in.op = NAME;			else if( r->in.op == REG ) r->in.op = OREG;			else if( r->in.op != OREG ) cerror( "STASG-r" );			size = p->stn.stsize;			if( size <= 0 || size > 65535 )				cerror("structure size <0=0 or >65535");			switch(size) {				case 1:					putstr("	movb	");					break;				case 2:					putstr("	movw	");					break;				case 4:					putstr("	movl	");					break;				case 8:					putstr("	movq	");					break;				default:					printf("	movc3	$%d,", size);					break;			}			adrput(r);			if( p->in.op == STASG ){				putchar(',');				adrput(l);				putchar('\n');				}			else				putstr(",(sp)\n");			if( r->in.op == NAME ) r->in.op = ICON;			else if( r->in.op == OREG ) r->in.op = REG;			}		break;	default:		cerror( "illegal zzzcode" );		}	}/* * collapsible(dest, src) -- if a conversion with a register destination *	can be accomplished in one instruction, return the type of src *	that will do the job correctly; otherwise return 0.  Note that *	a register must always end up having type INT or UNSIGNED. */intcollapsible(dest, src)NODE *dest, *src;{	int st = src->in.type;	int dt = dest->in.type;	int newt = 0;	/*	 * Are there side effects of evaluating src?	 * If the derived type will not be the same size as src,	 * we may have to use two steps.	 */	if (tlen(src) > tlen(dest)) {		if (tshape(src, STARREG))			return (0);		if (src->in.op == OREG && R2TEST(src->tn.rval))			return (0);		}	/*	 * Can we get an object of dest's type by punning src?	 * Praises be to great Cthulhu for little-endian machines...	 */	if (st == CHAR && dt == USHORT)		/*		 * Special case -- we must sign-extend to 16 bits.		 */		return (0);	if (tlen(src) < tlen(dest))		newt = st;	else		newt = dt;	return (newt);	}rmove( rt, rs, t ) TWORD t; {	printf( "	%s	%s,%s\n",#ifdef FORT		!Oflag ? (t==DOUBLE ? "movq" : "movl") :#endif		(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),		rnames[rs], rnames[rt] );	}struct resprefrespref[] = {	INTAREG|INTBREG,	INTAREG|INTBREG,	INAREG|INBREG,	INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,	INTEMP,	INTEMP,	FORARG,	FORARG,	INTEMP,	INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,	0,	0 };setregs(){ /* set up temporary registers */	fregs = 6;	/* tbl- 6 free regs on VAX (0-5) */	;	}rewfld( p ) NODE *p; {	return(1);	}callreg(p) NODE *p; {	return( R0 );	}base( p ) register NODE *p; {	register int o = p->in.op;	if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */	if( o==REG ) return( p->tn.rval );    if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)		return( p->in.left->tn.rval );    if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )		return( p->tn.rval + 0200*1 );	if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );	if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );	if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG	  && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )		return( p->in.left->in.left->tn.rval + 0200*(1+2) );	return( -1 );	}offset( p, tyl ) register NODE *p; int tyl; {	if( tyl==1 &&	    p->in.op==REG &&	    (p->in.type==INT || p->in.type==UNSIGNED) )		return( p->tn.rval );	if( p->in.op==LS &&	    p->in.left->in.op==REG &&	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&	    p->in.right->in.op==ICON &&	    p->in.right->in.name[0]=='\0' &&	    (1<<p->in.right->tn.lval)==tyl)		return( p->in.left->tn.rval );	if( tyl==2 &&	    p->in.op==PLUS &&	    (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&	    p->in.left->in.op==REG &&	    p->in.right->in.op==REG &&	    p->in.left->tn.rval==p->in.right->tn.rval )		return( p->in.left->tn.rval );	return( -1 );	}makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {	register NODE *t;	register int i;	NODE *f;	p->in.op = OREG;	f = p->in.left; 	/* have to free this subtree later */	/* init base */	switch (q->in.op) {		case ICON:		case REG:		case OREG:			t = q;			break;		case MINUS:			q->in.right->tn.lval = -q->in.right->tn.lval;		case PLUS:			t = q->in.right;			break;		case INCR:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?