616 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			616 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Header$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
/*
 | 
						|
 * Motorola 68020 auxiliary functions
 | 
						|
 */
 | 
						|
 | 
						|
/* With pc-relative modes the offset is calulated from the address of the 
 | 
						|
 * extension word. This address is not known until the instruction opcode(s)
 | 
						|
 * have been emitted. Since this address is unknown, the offset from pc
 | 
						|
 * cannot be calculated correctly, so it cannot immediately be decided whether
 | 
						|
 * to use mode 072 (pc-relative with 16 bit offset) or mode 073 (pc_relative
 | 
						|
 * with possibly 32 bit offset) Because of this, instruction opcodes
 | 
						|
 * are not really emitted right away, but temporarily stored. This way
 | 
						|
 * the address of the extension word is known so the offset can be calculated
 | 
						|
 * correctly and it then can be decided to use mode 072 or 073; this can be
 | 
						|
 * altered in the instruction opcode, if necessary. For the sake of consistency
 | 
						|
 * the effective address(es) are also stored temporarily. The instruction is
 | 
						|
 * then emitted in one go, by emit_instr().
 | 
						|
 */
 | 
						|
 | 
						|
emit_instr()
 | 
						|
{
 | 
						|
	register instr_t *ip;
 | 
						|
 | 
						|
	for (ip=instr; ip<instrp; emit2(ip++->i_word)) {
 | 
						|
#ifdef RELOCATION
 | 
						|
		RELOMOVE(relonami, ip->i_relonami);
 | 
						|
		if (ip->i_reloinfo)
 | 
						|
			newrelo(ip->i_relotype, ip->i_reloinfo | RELBR | RELWR);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifdef RELOCATION
 | 
						|
t_emit2(word, relotype, reloinfo, relnm)
 | 
						|
short word;
 | 
						|
short relotype;
 | 
						|
valu_t relnm;
 | 
						|
#else
 | 
						|
t_emit2(word)
 | 
						|
short word;
 | 
						|
#endif
 | 
						|
{
 | 
						|
#ifdef RELOCATION
 | 
						|
	if (instrp->i_reloinfo = reloinfo) {
 | 
						|
		RELOMOVE(instrp->i_relonami, relnm);
 | 
						|
		instrp->i_relotype = relotype;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	instrp++->i_word = word;
 | 
						|
	dot_offset += 2;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef RELOCATION
 | 
						|
t_emit4(words, relotype, reloinfo, relnm)
 | 
						|
long words;
 | 
						|
short relotype;
 | 
						|
valu_t relnm;
 | 
						|
#else
 | 
						|
t_emit4(words)
 | 
						|
long words;
 | 
						|
#endif
 | 
						|
{
 | 
						|
	T_EMIT2((short)(words>>16), relotype, reloinfo, relnm);
 | 
						|
	T_EMIT2((short)(words), 0, 0, 0);
 | 
						|
}
 | 
						|
 | 
						|
ea_1(sz, bits)
 | 
						|
{
 | 
						|
		/* Because displacements come in three sizes (null displacement,
 | 
						|
		 * word and long displacement), each displacement requires
 | 
						|
		 * two bits in the bittable, so two calls to small. Sometimes
 | 
						|
		 * one of these calls is a dummy call.
 | 
						|
		 */
 | 
						|
 | 
						|
	register flag;
 | 
						|
	register sm, sm1, sm2;
 | 
						|
 | 
						|
	if (mrg_1 > 074)
 | 
						|
		serror("no specials");
 | 
						|
	if ((flag = eamode[mrg_1>>3]) == 0)
 | 
						|
		if ((flag = eamode[010 + (mrg_1&07)]) == 0)
 | 
						|
			flag = eamode[015 + (sz>>6)];
 | 
						|
	if ((mrg_1 & 070) == 010)
 | 
						|
		checksize(sz, 2|4);
 | 
						|
	bits &= ~flag;
 | 
						|
	if (bits)
 | 
						|
		serror("bad addressing category");
 | 
						|
	if (mrg_1==073 && (ffew_1 & 0200) == 0 && (bd_1.typ & ~S_DOT) == DOTTYP)
 | 
						|
		bd_1.val -= (DOTVAL + dot_offset);
 | 
						|
 | 
						|
	if ( (mrg_1==073) || (mrg_1&070)==060 ) {
 | 
						|
		sm = (
 | 
						|
			(mrg_1==073 && (bd_1.typ & ~S_DOT)==DOTTYP)
 | 
						|
		      ||
 | 
						|
			(bd_1.typ == S_ABS)
 | 
						|
		     );
 | 
						|
		if (small(sm && fitw(bd_1.val), 2)) {
 | 
						|
			sm = (
 | 
						|
				(sm1 = ((ffew_1 & 0307)==0 && fitb(bd_1.val)))
 | 
						|
			      ||
 | 
						|
				(sm2 = ((ffew_1 & 0307)==0100 && mrg_1==073))
 | 
						|
			      ||
 | 
						|
				(bd_1.val==0)
 | 
						|
			     );
 | 
						|
			if (small(sm,2)) {
 | 
						|
				if (sm1) {	/* brief format extension */
 | 
						|
				    T_EMIT2((ffew_1&0177000) | lowb(bd_1.val),
 | 
						|
								    0, 0, 0);
 | 
						|
				    return;
 | 
						|
				}
 | 
						|
				if (sm2) {
 | 
						|
					/* change mode to 072 in opcode word */
 | 
						|
				    instr->i_word &= ~1;
 | 
						|
				    T_EMIT2(loww(bd_1.val), 0, 0, 0);
 | 
						|
				    return;
 | 
						|
				}
 | 
						|
				ffew_1 &= ~040;	/* null displacement */
 | 
						|
			}
 | 
						|
			else
 | 
						|
				ffew_1 &= ~020;		/* word displacement */
 | 
						|
		} else
 | 
						|
			sm = small(0,2); /* dummy call */
 | 
						|
 | 
						|
		if (ffew_1 & 3) {
 | 
						|
			sm = (od_1.typ == S_ABS);
 | 
						|
			if (small(sm && fitw(od_1.val), 2))
 | 
						|
				ffew_1 &= small(od_1.val==0, 2) ? ~2 : ~1;
 | 
						|
			else
 | 
						|
				sm = small(0,2); /* dummy call */
 | 
						|
		}
 | 
						|
 | 
						|
		assert((ffew_1 & 0410) == 0400);
 | 
						|
		T_EMIT2(ffew_1, 0, 0, 0);
 | 
						|
 | 
						|
		assert(ffew_1 & 060);
 | 
						|
		switch(ffew_1 & 060) {
 | 
						|
		case 020:
 | 
						|
			break;
 | 
						|
		case 040:
 | 
						|
			T_EMIT2(loww(bd_1.val), 0, 0, 0);
 | 
						|
			break;
 | 
						|
		case 060:
 | 
						|
			T_EMIT4(    bd_1.val,
 | 
						|
				    bd_1.typ,
 | 
						|
				    (mrg_1 == 073 && (ffew_1 & 0200) == 0)
 | 
						|
					? RELPC|RELO4
 | 
						|
					: RELO4,
 | 
						|
				    bd_rel1
 | 
						|
				);
 | 
						|
		}
 | 
						|
 | 
						|
		if (ffew_1 & 3) {
 | 
						|
			switch(ffew_1 & 3) {
 | 
						|
			case 1:
 | 
						|
				break;
 | 
						|
			case 2:
 | 
						|
				T_EMIT2(loww(od_1.val), 0, 0, 0);
 | 
						|
				break;
 | 
						|
			case 3:
 | 
						|
				T_EMIT4(od_1.val, od_1.typ, RELO4, od_rel1);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return; /* mode 060 and 073 have been dealt with */
 | 
						|
	}
 | 
						|
 | 
						|
	if (flag & FITW)
 | 
						|
		if (
 | 
						|
			! fitw(bd_1.val)
 | 
						|
			&&
 | 
						|
			(mrg_1 != 074 || ! fit16(bd_1.val))
 | 
						|
		)
 | 
						|
			nofit();
 | 
						|
	if (flag & FITB) {
 | 
						|
		if (
 | 
						|
			! fitb(bd_1.val)
 | 
						|
			&&
 | 
						|
			(mrg_1 != 074 || ! fit8(bd_1.val))
 | 
						|
		)
 | 
						|
			nofit();
 | 
						|
		if (mrg_1 == 074)
 | 
						|
			bd_1.val &= 0xFF;
 | 
						|
	}
 | 
						|
	if (flag & PUTL)
 | 
						|
		T_EMIT4(bd_1.val, bd_1.typ, (flag>>8), bd_rel1);
 | 
						|
	if (flag & PUTW)
 | 
						|
		T_EMIT2(loww(bd_1.val), bd_1.typ, (flag>>8), bd_rel1);
 | 
						|
}
 | 
						|
 | 
						|
ea_2(sz, bits)
 | 
						|
{ 
 | 
						|
	mrg_1  = mrg_2;
 | 
						|
	bd_1   = bd_2;
 | 
						|
	od_1   = od_2;
 | 
						|
	ffew_1 = ffew_2;
 | 
						|
	RELOMOVE(bd_rel1, bd_rel2);
 | 
						|
	RELOMOVE(od_rel1, od_rel2);
 | 
						|
	ea_1(sz, bits);
 | 
						|
}
 | 
						|
 | 
						|
checksize(sz, bits)
 | 
						|
{
 | 
						|
	if ((bits & (1 << (sz>>6))) == 0)
 | 
						|
		serror("bad size");
 | 
						|
}
 | 
						|
 | 
						|
checkscale(val)
 | 
						|
valu_t val;
 | 
						|
{
 | 
						|
	int v = val;
 | 
						|
 | 
						|
	if (v != val) v = 0;
 | 
						|
	switch(v) {
 | 
						|
	case 1:		return 0;
 | 
						|
	case 2:		return 1<<9;
 | 
						|
	case 4:		return 2<<9;
 | 
						|
	case 8:		return 3<<9;
 | 
						|
	default:	serror("bad scale"); return 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
badoperand()
 | 
						|
{
 | 
						|
	serror("bad operands");
 | 
						|
}
 | 
						|
 | 
						|
shift_op(opc, sz)
 | 
						|
{
 | 
						|
	if (mrg_1 < 010 && mrg_2 < 010) {
 | 
						|
		T_EMIT2((opc & 0170470) | sz | mrg_1<<9 | mrg_2, 0, 0, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (bd_1.typ != S_ABS || mrg_1 != 074) {
 | 
						|
		badoperand();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_2 < 010) {
 | 
						|
		fit(fit3(bd_1.val));
 | 
						|
		T_EMIT2((opc & 0170430) | sz | low3(bd_1.val)<<9 | mrg_2,0,0,0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	checksize(sz, 2);
 | 
						|
	fit(bd_1.val == 1);
 | 
						|
	T_EMIT2((opc & 0177700) | mrg_2, 0, 0, 0);
 | 
						|
	ea_2(SIZE_W, MEM|ALT);
 | 
						|
}
 | 
						|
 | 
						|
bitop(opc)
 | 
						|
{
 | 
						|
	register bits;
 | 
						|
 | 
						|
	bits = DTA|ALT;
 | 
						|
	if (opc == 0 && (mrg_1 < 010 || mrg_2 != 074))
 | 
						|
		bits = DTA;
 | 
						|
	if (mrg_1 < 010) {
 | 
						|
		T_EMIT2(opc | 0400 | mrg_1<<9 | mrg_2, 0, 0, 0);
 | 
						|
		ea_2(0, bits);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_1 == 074) {
 | 
						|
		T_EMIT2(opc | 04000 | mrg_2, 0, 0, 0);
 | 
						|
		ea_1(SIZE_W, 0);
 | 
						|
		ea_2(0, bits);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	badoperand();
 | 
						|
}
 | 
						|
 | 
						|
bitfield(opc, extension)
 | 
						|
{
 | 
						|
	T_EMIT2(opc | mrg_2, 0, 0, 0);
 | 
						|
	T_EMIT2(extension, 0, 0, 0);
 | 
						|
	ea_2(SIZE_L, (mrg_2 < 010) ? 0 : (CTR | ALT));
 | 
						|
}
 | 
						|
 | 
						|
add(opc, sz)
 | 
						|
{
 | 
						|
	if ((mrg_2 & 070) == 010)
 | 
						|
		checksize(sz, 2|4);
 | 
						|
	if (
 | 
						|
		mrg_1 == 074
 | 
						|
		&&
 | 
						|
		small(
 | 
						|
			bd_1.typ==S_ABS && fit3(bd_1.val),
 | 
						|
			sz==SIZE_L ? 4 : 2
 | 
						|
		     )
 | 
						|
	   ) {
 | 
						|
		T_EMIT2((opc&0400) | 050000 | low3(bd_1.val)<<9 | sz | mrg_2,
 | 
						|
								0, 0, 0);
 | 
						|
		ea_2(sz, ALT);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_1 == 074 && (mrg_2 & 070) != 010) {
 | 
						|
		T_EMIT2((opc&03000) | sz | mrg_2, 0, 0, 0);
 | 
						|
		ea_1(sz, 0);
 | 
						|
		ea_2(sz, DTA|ALT);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if ((mrg_2 & 070) == 010) {
 | 
						|
		T_EMIT2((opc&0170300) | (mrg_2&7)<<9 | sz<<1 | mrg_1, 0, 0, 0);
 | 
						|
		ea_1(sz, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (to_dreg(opc, sz, 0))
 | 
						|
		return;
 | 
						|
	if (from_dreg(opc, sz, ALT|MEM))
 | 
						|
		return;
 | 
						|
	badoperand();
 | 
						|
}
 | 
						|
 | 
						|
and(opc, sz)
 | 
						|
{
 | 
						|
	if (mrg_1 == 074 && mrg_2 >= 076) {	/* ccr or sr */
 | 
						|
		if (sz != SIZE_NON)
 | 
						|
			checksize(sz, mrg_2==076 ? 1 : 2);
 | 
						|
		else
 | 
						|
			sz = (mrg_2==076 ? SIZE_B : SIZE_W);
 | 
						|
		T_EMIT2((opc&07400) | sz | 074, 0, 0, 0);
 | 
						|
		ea_1(sz, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (sz == SIZE_NON)
 | 
						|
		sz = SIZE_DEF;
 | 
						|
	if (mrg_1 == 074) {
 | 
						|
		T_EMIT2((opc&07400) | sz | mrg_2, 0, 0, 0);
 | 
						|
		ea_1(sz, 0);
 | 
						|
		ea_2(sz, DTA|ALT);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if ((opc & 010000) == 0 && to_dreg(opc, sz, DTA))
 | 
						|
		return;
 | 
						|
	if (from_dreg(opc, sz, (opc & 010000) ? DTA|ALT : ALT|MEM))
 | 
						|
		return;
 | 
						|
	badoperand();
 | 
						|
}
 | 
						|
 | 
						|
to_dreg(opc, sz, bits)
 | 
						|
{
 | 
						|
	if ((mrg_2 & 070) != 000)
 | 
						|
		return(0);
 | 
						|
	T_EMIT2((opc & 0170000) | sz | (mrg_2&7)<<9 | mrg_1, 0, 0, 0);
 | 
						|
	ea_1(sz, bits);
 | 
						|
	return(1);
 | 
						|
}
 | 
						|
 | 
						|
from_dreg(opc, sz, bits)
 | 
						|
{
 | 
						|
	if ((mrg_1 & 070) != 000)
 | 
						|
		return(0);
 | 
						|
	T_EMIT2((opc & 0170000) | sz | (mrg_1&7)<<9 | 0400 | mrg_2, 0, 0, 0);
 | 
						|
	ea_2(sz, bits);
 | 
						|
	return(1);
 | 
						|
}
 | 
						|
 | 
						|
cmp(sz)
 | 
						|
{
 | 
						|
	register opc;
 | 
						|
 | 
						|
	if ((mrg_1&070) == 030 && (mrg_2&070) == 030) {
 | 
						|
		T_EMIT2(0130410 | sz | (mrg_1&7) | (mrg_2&7)<<9, 0, 0, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_1 == 074 && (mrg_2 & 070) != 010) {
 | 
						|
		if (mrg_2==074)
 | 
						|
			badoperand();
 | 
						|
		T_EMIT2(06000 | sz | mrg_2, 0, 0, 0);
 | 
						|
		ea_1(sz, 0);
 | 
						|
		ea_2(sz, DTA);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_2 < 020) {
 | 
						|
		if (mrg_2 >= 010) {
 | 
						|
			checksize(sz, 2|4);
 | 
						|
			opc = 0130300 | sz<<1;
 | 
						|
			mrg_2 &= 7;
 | 
						|
		} else
 | 
						|
			opc = 0130000 | sz;
 | 
						|
		T_EMIT2(opc | mrg_2<<9 | mrg_1, 0, 0, 0);
 | 
						|
		ea_1(sz, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	badoperand();
 | 
						|
}
 | 
						|
 | 
						|
link(sz, areg)
 | 
						|
{
 | 
						|
	if (sz == SIZE_NON) {
 | 
						|
		if (bd_2.typ == S_ABS && fitw(bd_2.val))
 | 
						|
			sz = SIZE_W;
 | 
						|
		else
 | 
						|
			sz = SIZE_L;
 | 
						|
	}
 | 
						|
	checksize(sz, 2|4);
 | 
						|
	if (sz == SIZE_W)
 | 
						|
		T_EMIT2(047120 | areg, 0, 0, 0);
 | 
						|
	else /* sz == SIZE_L */
 | 
						|
		T_EMIT2(044010 | areg, 0, 0, 0);
 | 
						|
	ea_2(sz, 0);
 | 
						|
}
 | 
						|
 | 
						|
move(sz)
 | 
						|
{
 | 
						|
	register opc;
 | 
						|
 | 
						|
	if (mrg_1 > 074 || mrg_2 > 074) {
 | 
						|
		move_special(sz);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (sz == SIZE_NON)
 | 
						|
		sz = SIZE_DEF;
 | 
						|
	if (
 | 
						|
		mrg_2<010
 | 
						|
		&&
 | 
						|
		mrg_1==074
 | 
						|
		&&
 | 
						|
		sz==SIZE_L
 | 
						|
		&&
 | 
						|
		small(bd_1.typ==S_ABS && fitb(bd_1.val), 4)
 | 
						|
	) {
 | 
						|
		T_EMIT2(070000 | mrg_2<<9 | lowb(bd_1.val), 0, 0, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	switch (sz) {
 | 
						|
	case SIZE_B:	opc = 010000; break;
 | 
						|
	case SIZE_W:	opc = 030000; break;
 | 
						|
	case SIZE_L:	opc = 020000; break;
 | 
						|
	}
 | 
						|
	T_EMIT2(opc | mrg_1 | (mrg_2&7)<<9 | (mrg_2&070)<<3, 0, 0, 0);
 | 
						|
	ea_1(sz, 0);
 | 
						|
	ea_2(sz, ALT);
 | 
						|
}
 | 
						|
 | 
						|
move_special(sz)
 | 
						|
{
 | 
						|
	if (mrg_2 >= 076) {
 | 
						|
		if (sz != SIZE_NON)
 | 
						|
			checksize(sz, 2);
 | 
						|
		T_EMIT2(042300 | (mrg_2==076?0:01000) | mrg_1, 0, 0, 0);
 | 
						|
		ea_1(SIZE_W, DTA);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_1 >= 076) {
 | 
						|
		if (sz != SIZE_NON)
 | 
						|
			checksize(sz, 2);
 | 
						|
		T_EMIT2(040300 | (mrg_1==076?01000:0) | mrg_2, 0, 0, 0);
 | 
						|
		ea_2(SIZE_W, DTA|ALT);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (sz != SIZE_NON)
 | 
						|
		checksize(sz, 4);
 | 
						|
	if (mrg_1==075 && (mrg_2&070)==010) {
 | 
						|
		T_EMIT2(047150 | (mrg_2&7), 0, 0, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_2==075 && (mrg_1&070)==010) {
 | 
						|
		T_EMIT2(047140 | (mrg_1&7), 0, 0, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	badoperand();
 | 
						|
}
 | 
						|
 | 
						|
movem(dr, sz, regs)
 | 
						|
{
 | 
						|
	register i;
 | 
						|
	register r;
 | 
						|
 | 
						|
	if ((mrg_2>>3) == 04) {
 | 
						|
		r = regs; regs = 0;
 | 
						|
		for (i = 0; i < 16; i++) {
 | 
						|
			regs <<= 1;
 | 
						|
			if (r & 1)
 | 
						|
				regs++;
 | 
						|
			r >>= 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	checksize(sz, 2|4);
 | 
						|
	if ((mrg_2>>3)-3 == dr)
 | 
						|
		badoperand();
 | 
						|
	T_EMIT2(044200 | dr<<10 | (sz & 0200) >> 1 | mrg_2, 0, 0, 0);
 | 
						|
	T_EMIT2(regs, 0, 0, 0);
 | 
						|
	i = CTR;
 | 
						|
	if (dr == 0 && (mrg_2&070) == 040)
 | 
						|
		i = MEM;
 | 
						|
	if (dr != 0 && (mrg_2&070) == 030)
 | 
						|
		i = MEM;
 | 
						|
	if (dr == 0)
 | 
						|
		i |= ALT;
 | 
						|
	ea_2(sz, i);
 | 
						|
}
 | 
						|
 | 
						|
movep(sz)
 | 
						|
{
 | 
						|
	checksize(sz, 2|4);
 | 
						|
	if (mrg_1<010 && (mrg_2&070)==050) {
 | 
						|
		T_EMIT2(0610 | (sz & 0200)>>1 | mrg_1<<9 | (mrg_2&7), 0, 0, 0);
 | 
						|
		ea_2(sz, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (mrg_2<010 && (mrg_1&070)==050) {
 | 
						|
		T_EMIT2(0410 | (sz & 0200)>>1 | mrg_2<<9 | (mrg_1&7), 0, 0, 0);
 | 
						|
		ea_1(sz, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	badoperand();
 | 
						|
}
 | 
						|
 | 
						|
branch(opc, exp)
 | 
						|
expr_t exp;
 | 
						|
{
 | 
						|
	register sm;
 | 
						|
 | 
						|
	exp.val -= (DOTVAL + 2);
 | 
						|
	if ((pass == PASS_2) 
 | 
						|
	    &&
 | 
						|
	    (exp.val > 0)
 | 
						|
	    &&
 | 
						|
	    ((exp.typ & S_DOT) == 0)
 | 
						|
	   )
 | 
						|
		exp.val -= DOTGAIN;
 | 
						|
	sm = fitw(exp.val);
 | 
						|
	if ((exp.typ & ~S_DOT) != DOTTYP)
 | 
						|
		sm = 0;
 | 
						|
	if (small(sm,2)) {
 | 
						|
		if (small(fitb(exp.val),2)) {
 | 
						|
			if (exp.val == 0)
 | 
						|
				T_EMIT2(047161, 0, 0, 0);	/* NOP */
 | 
						|
			else if (exp.val == -1) {
 | 
						|
				T_EMIT2(047161, 0, 0, 0);
 | 
						|
				serror("bad branch offset");
 | 
						|
			} else
 | 
						|
				T_EMIT2(opc | lowb(exp.val), 0, 0, 0);
 | 
						|
		} else {
 | 
						|
			T_EMIT2(opc, 0, 0, 0);
 | 
						|
			T_EMIT2(loww(exp.val), 0, 0, 0);
 | 
						|
		}
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	sm = small(0,2);	/* dummy call; two calls to small per branch */
 | 
						|
	T_EMIT2(opc | 0377, 0, 0, 0); /* 4 byte offset */
 | 
						|
	T_EMIT4(exp.val, exp.typ, RELPC|RELO4, relonami);
 | 
						|
}
 | 
						|
 | 
						|
cpbcc(opc, exp)
 | 
						|
expr_t exp;
 | 
						|
{
 | 
						|
	register sm;
 | 
						|
 | 
						|
	exp.val -= (DOTVAL + 2);
 | 
						|
	if ((pass == PASS_2) 
 | 
						|
	    &&
 | 
						|
	    (exp.val > 0)
 | 
						|
	    &&
 | 
						|
	    ((exp.typ & S_DOT) == 0)
 | 
						|
	   )
 | 
						|
		exp.val -= DOTGAIN;
 | 
						|
	sm = fitw(exp.val);
 | 
						|
	if ((exp.typ & ~S_DOT) != DOTTYP)
 | 
						|
		sm = 0;
 | 
						|
	if (small(sm,2)) {
 | 
						|
		T_EMIT2(opc, 0, 0, 0);
 | 
						|
		T_EMIT2(loww(exp.val), 0, 0, 0);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	
 | 
						|
	T_EMIT2(opc | 0100, 0, 0, 0); /* 4 byte offset */
 | 
						|
		/* NB: no coprocessor defined extension words are emitted */
 | 
						|
	T_EMIT4(exp.val, exp.typ, RELPC|RELO4, relonami);
 | 
						|
}
 | 
						|
 | 
						|
ea7071(sz)
 | 
						|
{
 | 
						|
	mrg_2 = 071;
 | 
						|
	switch (sz) {
 | 
						|
	case SIZE_B:
 | 
						|
		badoperand();
 | 
						|
	case SIZE_W:
 | 
						|
		mrg_2 = 070;
 | 
						|
	case SIZE_L:
 | 
						|
		return;
 | 
						|
	case SIZE_NON:
 | 
						|
		break;
 | 
						|
	}
 | 
						|
		/* If this absolute address is in program space, and if we
 | 
						|
		 * can assume that the only references to program space are made
 | 
						|
		 * by instructins like 'jsr', 'jmp', 'lea' and 'pea', it might
 | 
						|
		 * be possible to use a (PC,d16) effective address mode instead
 | 
						|
		 * of absolute long. This is done here. If this scheme is in
 | 
						|
		 * some way undesirable (e.g. when references to program space
 | 
						|
		 * are made by instructions with more than one opcode word or by
 | 
						|
		 * second effective addresses in instructions), the rest
 | 
						|
		 * of this routine can simply be removed and replaced by the
 | 
						|
		 * next two lines (which of course are in comment brackets now).
 | 
						|
	if (small(bd_2.typ == S_ABS && fitw(bd_2.val), 2))
 | 
						|
		mrg_2 = 070;
 | 
						|
		 */
 | 
						|
	if (pass == PASS_1) {
 | 
						|
			/* Reserve a bit in the bittable; in the following
 | 
						|
			 * passes one call to small() will be done, but know yet
 | 
						|
			 * which one, because bd_2.typ cannot be trusted yet.
 | 
						|
			 */
 | 
						|
		small(0, 2);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if ((bd_2.typ & ~S_DOT) == DOTTYP) {
 | 
						|
		if (small(fitw(bd_2.val-(DOTVAL+2)), 2)) {
 | 
						|
			bd_2.val -= (DOTVAL+2);
 | 
						|
			mrg_2 = 072;
 | 
						|
		}
 | 
						|
	} else
 | 
						|
		if (small(bd_2.typ == S_ABS && fitw(bd_2.val), 2))
 | 
						|
			mrg_2 = 070;
 | 
						|
}
 |