File:  [MW Coherent from dump] / coherent / d / bin / cc / c / n1 / i8086 / amd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * This routine sets the addressing flags for a tree node.
 * This version is for both the SMALL and LARGE model iAPX-86.
 * There is no provision for double indexed address modes;
 * the compiler does not attempt to use them at this time.
 */
#ifdef   vax
#include "INC$LIB:cc1.h"
#else
#include "cc1.h"
#endif

TREE	*findoffs();

/*
 * Determine access mode.
 * The mode set is stored into the 't_flag' field.
 * The subtrees have already been marked.
 * Knows how the output writer will map
 * the logical segments into physical segments.
 * This routine is usually called by 'walk'.
 */
amd(tp, ptp)
register TREE	*tp;
TREE		*ptp;
{
	register TREE	*xp;
	register ival_t	half;
	register int	op;
	register REGNAME r;
	register FLAG	flag;
	register FLAG	mask;
	register KIND	kind;
	register TYPE	t;
	register lval_t	n;
	register int	i;
	register int	seg;

	if ((op=tp->t_op) == LEAF) {
		tp->t_flag = tp->t_lp->t_flag;
		return;
	}
	flag = 0;
	if (op==ICON || op==LCON) {
		if ((n=grabnval(tp)) == 0)
			flag |= T_0;
		else if (n == 1)
			flag |= T_1;
		else if (n == 2)
			flag |= T_2;
		if (n>=-128 && n<=127)
			flag |= T_BYTE;
		if (op == LCON) {
			flag |= T_LCN;
			half = lower(n);
			if (half == 0)
				flag |= T_LHC;
			if (half == -1)
				flag |= T_LHS;
			half = upper(n);
			if (half == 0)
				flag |= T_UHC;
			if (half == -1)
				flag |= T_UHS;
		} else
			flag |= T_ICN;
	}
	if (op == DCON) {
		flag |= T_DCN;
		i = 0;
		while (i<sizeof(dval_t) && tp->t_dval[i]==0)
			++i;
		if (i == sizeof(dval_t))
			flag |= T_0;
	}
	if (op == REG) {
		flag |= T_DIR;
		kind = pertype[tp->t_type].p_kind;
		if ((reg[tp->t_reg].r_lvalue&kind) != 0)
			flag |= T_LREG;
		if ((reg[tp->t_reg].r_rvalue&kind) != 0)
			flag |= T_RREG;
#if !ONLYSMALL
		if (tp->t_reg==SSSP || tp->t_reg==SSBP)
			flag |= T_SREG;
#endif
	} else if (op == ADDR) {
		if (isvariant(VSMALL))
			flag |= T_ADS;
		else {
			xp = tp->t_lp;
			if (xp->t_op==LID || xp->t_op==GID) {
				switch (xp->t_seg) {
				case SCODE:
				case SLINK:
					flag |= T_ACS;
					break;
				case SPURE:
					if (isvariant(VRAM))
						flag |= T_ADS;
					else
						flag |= T_ACS;
					break;
				case SSTRN:
					if (notvariant(VROM))
						flag |= T_ADS;
					else
						flag |= T_ACS;
					break;
				case SDATA:
				case SBSS:
					flag |= T_ADS;
					break;
				}
			} 	
		}
	} else if (op==LID || op==GID) {
#if ONLYSMALL
		flag |= T_DIR;
#else
		seg = tp->t_seg;
		if (isvariant(VSMALL)
		|| (ptp!=NULL && ptp->t_op==CALL && tp==ptp->t_lp)
		|| seg==SCODE
		|| seg==SLINK
		|| (seg==SPURE && notvariant(VRAM)))
			flag |= T_DIR;
#endif
	} else if ((op==ADD || op==SUB) && ispoint(t=tp->t_type)) {
		mask = T_CON;
		if (op == SUB)
			mask = T_NUM;
		xp = tp;
		do {
			if ((xp->t_rp->t_flag&mask) == 0)
				break;
			xp = xp->t_lp;
		} while (xp->t_op==ADD || xp->t_op==SUB);
		if ((xp->t_flag&T_REG) != 0) {
			while (xp->t_op == LEAF)
				xp = xp->t_lp;
			r = xp->t_reg;
#if !ONLYSMALL
			if (notvariant(VSMALL)) {
				if (r == SSBP)
					flag |= T_LSS;
			} else {
#endif
				if (r==SI || r==DI || r==BX || r==BP)
					flag |= T_LEA;
#if !ONLYSMALL
			}
#endif
		}
	} else if (op == STAR) {
		xp = findoffs(tp);
		if ((xp->t_flag&T_CON) != 0 && notvariant(VLARGE))
			flag |= T_DIR;
		else if ((xp->t_flag&T_REG) != 0) {
			while (xp->t_op == LEAF)
				xp = xp->t_lp;
			r = xp->t_reg;
#if !ONLYSMALL
			if (notvariant(VSMALL)) {
				if (r==SSBP
				||  r==ESSI || r==ESDI || r==ESBX
				||  r==DSSI || r==DSDI || r==DSBX)
					flag |= T_DIR;
			} else {
#endif
				if (r==BP
				||  r==SI || r==DI || r==BX)
					flag |= T_DIR;
#if !ONLYSMALL
			}
#endif
		}
		flag |= T_OFS;
	}
	tp->t_flag = flag;
}

/*
 * Given a pointer to an offset type
 * tree, run down the chain of indirections
 * and additions, looking for the tree that
 * must be loaded into a register to get
 * an addressable tree. Return a pointer to
 * this tree.
 */
TREE *
findoffs(tp)
register TREE *tp;
{
	register flag, ct=0, op;

	while (tp->t_op == LEAF)
		tp = tp->t_lp;
	for (;;) {
		tp = tp->t_lp;
		switch (op=tp->t_op) {
			case SUB:	/* can't load neg addr */
			    if(tp->t_rp->t_flag&T_NUM)
				break;
			    return tp;
			case ADD: /* add one addr max */
			    if((flag=(tp->t_rp->t_flag))&T_NUM)
				break;
			    else
				if(flag&T_CON&&0==ct++)
				    break;
			default:
			    return tp;
		}
	}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.