File:  [Research Unix] / researchv9 / cmd / sun / as / op.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#ifndef lint
static	char sccsid[] = "@(#)op.c 1.1 86/02/03 Copyr 1985 Sun Micro";
#endif

/*
 * Copyright (c) 1985 by Sun Microsystems, Inc.
 */

#include "as.h"

/* move_op - uses two effective addresses */

move_op( ip )
    struct ins_bkt *ip;
{
	register struct oper *op1, *op2;
	int r1, r2;
	/*
	 * opval_i[0] -- movX   eaddr,eaddr
	 * opval_i[1] -- movl   Areg,USP
	 * opval_i[2] -- movw	eaddr,cc
	 * opval_i[3] -- movw	cc,eaddr
	 */

	op1 = operands;
	op2 = &operands[1];
	r1 = (int)op1->value_o;
	r2 = (int)op2->value_o;

	if (sr_addr(op1)){
		wcode[0] = ip->opval_i[3];
		if (r1 != CCREG) wcode[0] ^= 1<<9;
		eaddr(op2, SUBOP_W, 0);
	} else if (sr_addr(op2)){
		wcode[0] = ip->opval_i[2];
		if (r2 != CCREG) wcode[0] ^= 1<<9;
		eaddr(op1, SUBOP_W, 1);
	} else if (usp_addr(op1)) {
		wcode[0] = ip->opval_i[1] | 0x8 | (r2 & 07);
	} else if (usp_addr(op2)) {
		wcode[0] = ip->opval_i[1] | (r1 & 07);
	} else {
		unsigned reg, mode, source;
		wcode[0] = 0;
		/* get source address */
		eaddr(op1, ip->subop_i, 0);
		source = wcode[0];		/* save it */
		wcode[0] = 0;
		/* get destination address */
		eaddr(op2, ip->subop_i, 1);
		/* flip around destination address */
		reg = wcode[0] & 07;
		mode = (wcode[0] >> 3) & 07;
		/* assemble instruction */
		wcode[0] = ip->opval_i[0] | (reg << 9) | (mode << 6) | source;
	}
}
/* two_ops - these are of the forms:
	xxx Dn,<eaddr>
	xxx <eaddr>,Dn
	xxx #yyy,<eaddr>
	xxx <eaddr>,An
 */

two_op( ip )
	register struct ins_bkt *ip;
{
	register struct oper *op1, *op2;
	int r1, r2;
	int wrtflg = ip->touchop_i&TOUCH2((BW|WW|LW)); /* 2nd operand write-to unless compare */
	subop_t size = ip->subop_i;
	op1 = &operands[0];
	op2 = &operands[1];
	r1 = (int)op1->value_o & 07;
	r2 = (int)op2->value_o & 07;

	/*
	 * opval_i[0] -- op  eaddr,dreg
	 * opval_i[1] -- op  eaddr,areg
	 * opval_i[2] -- op  #imm,eaddr   OR  0xffff
	 * opval_i[3] -- op  #imm,cc
	 */

	if (areg_addr(op2)){
	    /* addl  xxx,a0 */
	    wcode[0] = ip->opval_i[1] |(r2<<9);
	    eaddr(op1, size, 0);
	} else if (op1->type_o == T_IMMED && ip->opval_i[2] != 0xffff ) {
	    if (sr_addr(op2)){
		/* andb	#imm,cc	*/
		wcode[0] = ip->opval_i[3];
		/* byte-size to cc only, word-size to sr only */
		if (!((op2->value_o == SRREG) ^ (size == SUBOP_B)))
		    PROG_ERROR( E_OPERAND );
		rel_val(op1, (size==SUBOP_L)?SUBOP_L:SUBOP_W, 0);
	    } else {
		/* andw #imm,eaddr */
		wcode[0] = ip->opval_i[2];
		rel_val(op1, (size==SUBOP_L)?SUBOP_L:SUBOP_W, 0);
		eaddr(op2, size, wrtflg);
	    }
	} else {
	    wcode[0] = ip->opval_i[0];
	    /* notice closely:
	     *   op	d0,d1
	     * appears ambiguous. Actually, it is not.
	     * eor takes register only as source. other ops only 
	     * as destination.
	     */
	    if (!dreg_addr(op2) || ip->op_i == OP_EOR) {
		/* op	dreg,eaddr & eorl dreg,dreg */
		wcode[0] |= 0400|(r1<<9);
		eaddr(op2, size, wrtflg);
	    } else {
		/* op	eaddr,dreg  and op dreg,dreg */
		/* note that mulu #imm,dreg ends up here, too */
		wcode[0] |= (r2 << 9);
		eaddr(op1, size, 0);
	    }
	}
}
/* one_ops - install opr, check for exactly one operand and compute eaddr */

one_op( ip )
    struct ins_bkt *ip;
{
	register struct oper *op = operands;
	wcode[0] = ip->opval_i[0];
	switch (ip->op_i){
	case OP_CALL:
	case OP_BRANCH:
	    if (jsrflag && op->type_o == T_NORMAL && op->sym_o != 0){
		/* make this a pc-relative */
		/*
		op->value_o -= dot+2;
		*/
		op->type_o = T_PCPLUS; /* MAGIC!! */
		op->reg_o  = PCREG;
	    }
	}
	eaddr(op, ip->subop_i, ip->touchop_i&TOUCH1(LW|WW|BW));
}


/* no_op(opr) -- places opr in wcode[0]. */

no_op(ip)
    struct ins_bkt *ip;
{
    wcode[0] = ip->opval_i[0];
};

/* branch_op - process branch offsets */
/* also handle DBcc instructions */
branch_op(ip)
    struct ins_bkt *ip;
{
	long offs = 0;
	register struct oper *opp = operands;

	wcode[0] = ip->opval_i[0];
	if (ip->noper_i == 2){
	    wcode[0] |= opp->value_o;
	    opp  += 1;
	}
	if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){
		/* external branch -- good luck */
		;
	} else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){
		PROG_ERROR(E_RELOCATE);
	} else {
		opp->sym_o = 0;	/* mark as non relocateable expression */
	}
	offs = opp->value_o - (dot + 2);
	if (offs > 32767L || offs < -32768L)
		PROG_ERROR(E_OFFSET);
	opp->value_o = (int)offs;
	rel_val(opp, SUBOP_W, opp->sym_o != 0);
}


brnchs_op(ip)
    struct ins_bkt *ip;
{
	long offs = 0;
	register struct oper *opp = operands;

	wcode[0] = ip->opval_i[0];
	if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){
		/* external branch -- out of luck */
		PROG_ERROR(E_RELOCATE);
	} else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){
		PROG_ERROR(E_RELOCATE);
	} 
	offs = opp->value_o - (dot + 2);
	if (offs > 127 || offs < -128)
		PROG_ERROR(E_OFFSET);
	if (offs != 0){
	    wcode[0] |= offs & 0377;
	} else if ( ip->op_i != OP_CALL ){
	    /*
	     * this is not a bsr, and we have a PC-relative address of zero
	     * if we just spit this out as usual, it would look just like
	     * the beginning of a longer form of jump. So instead,
	     * we emit a "nop" instruction right here.
	     */
	    wcode[0] = 0x4e71;
	} else {
	    PROG_ERROR(E_OFFSET);
	}
}

/* it is not clear that we can get there from here.
 * If this is a 68020 instruction generation, then we can use
 * the long form of the branch. Otherwise, if this is an
 * unconditional, then we can use a long jump. Otherwise,
 * we must generate a branch-around-a-jump.
 */
brnchl_op(ip)
    struct ins_bkt *ip;
{
    register struct oper *opp = &operands[0];
    int offs;
    if (ext_instruction_set){
	wcode[0] = ip->opval_i[0] | 0377;
	if (opp->sym_o && ((opp->sym_o->attr_s & S_DEF) == 0)){
		/* external branch -- good luck */
		;
	} else if ((opp->sym_o==0) || (opp->sym_o->csect_s!=cur_csect_name)){
		/* PROG_ERROR(E_RELOCATE); */
	} else {
		opp->sym_o = 0;	/* mark as non relocateable expression */
	}
	offs = opp->value_o - (dot + 2);
	opp->value_o = (int)offs;
	rel_val(opp, SUBOP_L, opp->sym_o != 0);
    } else {
	/* this is not an extended-instruction set assembly */
	hard_branch( ip, opp );
    }
}

static
hard_branch( ip, opp )
    register struct ins_bkt *ip;
    register struct oper *opp;
{
    /* choose alternate opcode -- either long form or complement */
    wcode[0] = ip->opval_i[1];
    /*
     * if we are unconditional, just use the long mode.
     * otherwise, do the jump-around-jump
     */
    if (ip->subop_i == JALL){
	if (jsrflag && opp->type_o == T_NORMAL && opp->sym_o != 0){
	    /* make this a pc-relative */
	    /*
		opp->value_o -= dot+2;
	    */
	    opp->type_o = T_PCPLUS; /* MAGIC!! */
	    opp->reg_o  = PCREG;
	}
	eaddr(opp, SUBOP_L, 0);
	return;
    } else if (d2flag && (opp->type_o == T_NORMAL) ){
	/* we're really doing short displacements, anyway */
	branch_op( ip );
	return;
    } else {
	/* use complementary branch over jump */
	/* we'll fool eaddr() by building the jump instruction in wcode[0], then moving it */
	/* its address word, though, must be built in the right place */
	wcode[0] = 0x4EC0;		/* jmp xxxxxx */
	code_length = 4;		/* so far */
	eaddr(opp, SUBOP_L, 0);		/* the address */
	wcode[1] = wcode[0];
	wcode[0] = ip->opval_i[1] + code_length - 2;
    }
}
/*
 * generate a short or a long branch instruction as appropriate
 * note that:
 *		jra	foo
 *	foo:
 * is translated (by brnchs_op) to a nop.  If we attempt to
 * optimize this to generate no code, then after resolving
 * the span-dependent instructions, the value of
 * foo is the same as the address of the jra instruction.
 * Therefore, on pass 2, the jra looks like a jra .
 * Presumably, this could be fixed by keeping more information
 * after the sdi's are resolved
 */
jbrnch_op( ip )
	struct ins_bkt *ip;
{
	long offs = 0;
	register struct oper *opp = operands;
	int longsize, longsdi, useshort;

	if (opp->type_o != T_NORMAL || opp->sym_o == NULL) {
		/* not a relocatable operand */
		hard_branch( ip, opp );
	} else {
		offs = opp->value_o - (dot + 2);
		if (hflag && ip->op_i != OP_CALL)
		    useshort = 1;
		else
		    useshort = d2flag||jsrflag;
		if ((ip->subop_i == JALL) || ext_instruction_set){
		    longsize = 6;
		    longsdi = SDI6;
		} else {
		    longsize = 8;
		    longsdi = SDI8;
		}
		if (opp->flags_o & O_COMPLEX)	/* not a simple address */
			hard_branch( ip, opp );
		else if (pass == 1){
			if (cansdi) {
			    if (ip->op_i == OP_CALL && !Oflag &&
				operands->sym_o->value_s == 0 )
			    /* jbsr w/ forward reference */
				goto no_sdi;
			    code_length = makesdi(opp, dot + 2, 
				useshort ? SDI4 : longsdi);
			}
			else
		no_sdi:
			    code_length = useshort? 4 : longsize;
			put_rel( opp, SUBOP_L, dot+2, 0); /* may be to external */
		} else {
			/* pass 2 */
			if (opp->sym_o == 0
			 || opp->sym_o->csect_s != cur_csect_name
			 || offs < -32768L || offs > 32767L
			 || !cansdi ){
#ifdef EBUG
				if (debflag>1)
				    printf("jbrnch(2): external branch line %d offset 0x%X\n",
					line_no, dot);
#endif
				if (useshort) branch_op(ip);
				else          brnchl_op( ip );
			}else if (ip->op_i == OP_CALL && !Oflag &&
				  (operands->sym_o->value_s == 0 ||
				   operands->sym_o->value_s > dot ) ){
				cansdi = 0;    /* fake temperarily */
				hard_branch(ip, opp);
				cansdi = 1;
			}else if (offs > 127 || offs < -128){
#ifdef EBUG
				if (debflag>1)
				    printf("jbrnch(2): 4 byte branch line %d offset 0x%X\n",
					line_no, dot);
#endif
				branch_op(ip);
			}else{
#ifdef EBUG
				if (debflag>1)
				    printf("jbrnch(2): 2 byte branch line %d offset 0x%X\n",
					line_no, dot);
#endif
				brnchs_op(ip);
			}
		}
	}
	return;
}

 /* 
 * instructions of the form xxx Ax@+,Ay@+
 * and those of the forms   xxx Dx,Dy
 *                     or   xxx Ax@-,Ay@-
 */

regmem_op(ip)
    struct ins_bkt *ip;
{
	wcode[0] = ip->opval_i[0] 
		| (operands[0].value_o&07) | ((operands[1].value_o&07)<<9);
	if (operands[0].type_o == T_PREDEC ) {
		wcode[0] |= 010;
	}
}

/*
 * quick_op -- instructions such as "addqw	#7,d0"
 */

quick_op( ip )
    struct ins_bkt *ip;
{
    register int val = operands[0].value_o;
    if ( val <= 0 || val > 8 )
	PROG_ERROR( E_CONSTANT);
    if (val == 8 ) 
	val = 8;
    wcode[0] = ip->opval_i[0] | (val<<9);
    eaddr( &operands[1], ip->subop_i, 0);
}

/* shift op -	shift either a register or an effective address */

shift_op( ip )
    struct ins_bkt *ip;
{
	register struct oper *op1, *op2;
	op1 = &operands[0];
	op2 = &operands[1];
	/*
	 * opval_i[0] -- register-shift opcode
	 * opval_i[1] -- memory-shift opcode
	 */

	if (numops == 1) {
	    wcode[0] = ip->opval_i[1];
	    eaddr(op1, SUBOP_W, 1);
	} else {
	    int val1, val2;
	    wcode[0] = ip->opval_i[0];
	    val1 = (int)op1->value_o;
	    val2 = (int)op2->value_o;
	    if (op1->type_o==T_IMMED) {
		if (val1 == 8) val1 = 0;
	    } else {
		wcode[0] |=  040;
	    }
	    wcode[0] |= ((val1 & 07) << 9) | (val2 & 07);
	}
}
/* bit_op - of the form xxx Dn,<eaddr> or xxx #nnn,<eaddr> */

bit_op( ip )
	struct ins_bkt *ip;
{
	register struct oper *op1 ;
	/*
	 * opval_i[0] -- bit number dynamic
	 * opval_i[1] -- bit number static
	 */
	op1 = operands;

	wcode[0] = ip->opval_i[0];
	if (op1->type_o == T_REG ) {
	    /* <eaddr> is destination */
	    wcode[0] = ip->opval_i[0] | ((int)op1->value_o << 9);
	    eaddr(&operands[1], SUBOP_W, 1);
	} else {
	    wcode[0] = ip->opval_i[1];
	    rel_val(op1, SUBOP_W, 0);
	    eaddr(&operands[1], SUBOP_W, 1);
	}
}

/*
 * bitf_op -- single-operand bit-field instructions 
 */
bitf_op( ip )
    struct ins_bkt *ip;
{
    register struct oper *o = &operands[0];
    register flags = o->flags_o;
    wcode[0] = ip->opval_i[0];
    if (!(flags&O_BFLD))
	PROG_ERROR(E_OPERAND);
    wcode[1] = 0;
    if (flags&O_BFOREG)
	wcode[1] |= 1<<11;
    wcode[1] |= o->bfoffset_o << 6;
    if (flags&O_BFWREG)
	wcode[1] |= 1<<5;
    wcode[1] |= o->bfwidth_o;
    code_length += 2;
    o->flags_o &= ~O_BFLD;
    eaddr( o, SUBOP_W, 1);
}

/*
 * bitfr_op -- bit-field + register instructions.
 */
bitfr_op( ip )
    struct ins_bkt *ip;
{
    struct oper * r ;
    int reg;
    r = &operands[0];
    if (!(r->flags_o&O_BFLD)){
	/* first operand register */
	/* extract value, slide on down */
	reg = r->value_o;
	*r = operands[1];
    } else {
	/* second operand register */
	/* just extract value */
	reg = operands[1].value_o;
    }
    bitf_op( ip ); /* do most of the work; */
    wcode[1] |= reg << 12; /* finish off */
}

/* exg_op - instructions like exg rx,ry */

exg_op( ip )
	struct ins_bkt *ip;
{
	int r1, r2;
	register struct oper *op1, *op2;
	op1 = operands;
	op2 = &operands[1];
	r1 = (int)op1->value_o;
	r2 = (int)op2->value_o;

	wcode[0] = ip->opval_i[0];
	if (dreg(r1) && dreg(r2))
		wcode[0] |= 0100 | (r1 << 9) | r2;
	else if (areg(r1) && areg(r2))
		wcode[0] |= 0110 | ((r1 & 07) << 9) | (r2 & 07);
	else if (areg(r1) && dreg(r2))
		wcode[0] |= 0210 | (r2 << 9) | (r1 & 07);
	else if (dreg(r1) && areg(r2))
		wcode[0] |= 0210 | (r1 << 9) | (r2 & 07);
	else
		PROG_ERROR( E_OPERAND );
}		
/* reg_op - instructions that take one register operand */

reg_op( ip )
    struct ins_bkt *ip;
{
    wcode[0] = ip->opval_i[0] | (operands[0].value_o & 07);
}


/* link_op - form: link An,#<disp> */

link_op( ip )
    struct ins_bkt *ip;
{
    register int v = operands[1].value_o;
    /* 
     * opval_i[0] -- normal short form
     * opval_i[1] -- extended long form
     */
    if ( (ip->opval_i[0] == 0) || 		/* If linkl requested specifically, */
	v < -32768 || v > 32767 ||	/* or displacement too big for linkw, */ 
	!( operands[1].sym_o == NULL || operands[1].sym_o->attr_s & S_DEF))
					/* or displacement is relocatable !!, */
					{ /* try long form. */
	if (ext_instruction_set 	/* If generating 68020 code, */
	    && (ip->opval_i[1] != 0))	/* and linkw not requested specifically, */
					{ /* try long form. */
            if (!(operands[1].sym_o==NULL || operands[1].sym_o->attr_s&S_DEF)
                && pass==1 && cansdi){
                (void)makeddi( &operands[1], dot+code_length, SDIL, 0);
            }
	    wcode[0] = ip->opval_i[1] | (operands[0].value_o & 07);
	    rel_val(&operands[1], SUBOP_L, 0);
	    return;
	} else if ( v < -32768 || v > 32767)
	    PROG_ERROR(E_CONSTANT);
	/* else is external -- take pot luck */
    }
    wcode[0] = ip->opval_i[0] | (operands[0].value_o & 07);
    rel_val(&operands[1], SUBOP_W, 0);
}


/* movec_op - for the very weird movc instruction: movec rn,rc   */
/* 		where rc is in { usp, sfc, dfc, vbr }		 */

movec_op( ip )
    struct ins_bkt *ip;
{
    register struct oper *op1, *op2;
    register reg;
    register creg;
    static ctrl_reg_values[] = 
    /*  USP   SFC   DFC   VBR  CACR  CAAR   MSP   ISP */
    { 0x800,   0,    1, 0x801,   2, 0x802, 0x803, 0x804 };
    op1 = operands;
    op2 = &operands[1];
    wcode[0] = ip->opval_i[0];
    code_length = 4;
    if (ctrl_reg(op1->value_o)){
	    /* from control reg to user reg */
	    creg = op1->value_o;
	    reg  = op2->value_o;
    }else {
	    /* from user reg to control reg */
	    wcode[0] |= 1;
	    creg = op2->value_o;
	    reg  = op1->value_o;
    }
    creg = ctrl_reg_values[ creg - USPREG ];
    wcode[1] = ((reg&07)<<12) | creg;
    if(areg(reg)){
	wcode[1] |= 0x8000;
    }
}

/* moves_op - for the very weird movs instruction: 		 */
/* 		moves rn,eaddr or moves eaddr,rn	 	 */

moves_op( ip )
    struct ins_bkt *ip;
{
	register struct oper *op1, *op2;
	register reg;
	op1 = operands;
	op2 = &operands[1];
	wcode[0] = ip->opval_i[0];
	code_length = 4;
	if ( op1->type_o == T_REG ){
	    /* from register to other space */
	    reg = op1->value_o;
	    wcode[1] = 1<<11;
	    eaddr( op2, ip->subop_i, 1);
	} else {
	    /* from outer space to register */
	    reg = op2->value_o;
	    wcode[1] = 0;
	    eaddr( op1, ip->subop_i, 0);
	} 
	wcode[1] |= (reg&07)<<12;
	if(areg(reg)){
	    wcode[1] |= 0x8000;
	}
}


int reverse_bits( forward )
	int forward ;

/*
	result = forward with with 16 low order bits in reverse order.
*/

{
int bit, new ;
long i ;

new = 0 ;
bit = 0x8000 ;

for (i=0 ; i<16 ; i++ ) 
	{
	if (forward & 1) new |= bit ;
	forward = forward >> 1 ;
	bit = bit >> 1 ;
	}
return(new) ;
}

/* movem_op -	of the form: movem #xxx,<eaddr> or movem <eaddr>,#xxx */

movem_op( ip )
	struct ins_bkt *ip;
{
	register struct oper *op1, *op2;
	op1 = operands;
	op2 = &operands[1];
	switch (op1->type_o) 
		{
		case T_REGLIST:	/*	movem	<reglist>,<ea> */
			if (op2->type_o == T_PREDEC) /* reverse mask for an@- */
				op1->value_o = reverse_bits(op1->value_o) ;
		case T_IMMED:	/*	movem	#xxx,<ea> */
			{
			wcode[0] = ip->opval_i[0];
			rel_val(op1, SUBOP_W, 0);
			eaddr(op2, SUBOP_W, 1);
			break ;
			}
		default: 
			{
				/*	movem	<ea>,#xxx	*/
				/*	movem	<ea>,<reglist>	*/
			wcode[0] = ip->opval_i[1];
			rel_val(op2, SUBOP_W, 0);
			eaddr(op1, SUBOP_W, 0);
			}
		}
}

/* movep_op - of the form:  movep Dx,Ay@(d) or movep Ay@(d),Dx */

movep_op(ip)
	struct ins_bkt *ip;
{
	register struct oper *op1, *op2;
	int r1, r2;
	/*
	 * opval_i[0] -- memory-to-register
	 * opval_i[1] -- register-to-memory
	 */
	op1 = operands;
	op2 = &operands[1];
	r1 = (int)op1->value_o;
	r2 = (int)op2->value_o;
	if (op1->type_o == T_REG ) {
	    /* register-to-memory */
	    wcode[0] = ip->opval_i[1] | (r1 << 9) | (op2->reg_o & 07);
	    rel_val(op2, SUBOP_W, 0);		
	} else {
	    /* memory-to-register */
	    wcode[0] = ip->opval_i[0] | (r2 << 9) | (op1->reg_o & 07);
	    rel_val(op1, SUBOP_W, 0);
	}
}	


/* moveq -  form: moveq #<data>,Dn */

moveq_op( ip )
	struct ins_bkt *ip;
{
	register struct oper *op1, *op2;
	int r2;
	op1 = operands;
	op2 = &operands[1];
	r2 = (int)op2->value_o;
	if (op1->value_o > 0177 || op1->value_o < -0200)
		PROG_ERROR(E_CONSTANT);
	wcode[0] = ip->opval_i[0] | (r2 << 9) | ((short)op1->value_o & 0377);
}


/* trap - form: trap #xxx */

trap( ip )
	struct ins_bkt *ip;
{
        wcode[0] = ip->opval_i[0] | (((char)operands[0].value_o) & 017);
}

/* stop instruction -- form is stop #xxxx */
stop( ip )
	struct ins_bkt *ip;
{
        wcode[0] = ip->opval_i[0];
	rel_val( &operands[0], ip->subop_i, 0 );
}

/* rts instruction -- may or may not take an operand */
rts_op( ip )
	struct ins_bkt *ip;
{
	register struct oper *opp = operands;
	/*
	 * opval_i[0] -- no  operand
	 * opval_i[1] -- one operand
	 */
	if (numops == 1){
		/* new form -- with operand */
		wcode[0] = ip->opval_i[1];
		wcode[1] = 0xffff & opp->value_o;
		code_length = 4;
	} else {
		wcode[0] = ip->opval_i[0];
	}
}

/*
 *  chk2_op -- instructions of chk2X and cmp2X families: 
 *  take register number (plus one bit) in an extension word
 */
chk2_op( ip )
    struct ins_bkt *ip;
{
    /* 
     * opval_i[0] -- opcode 
     * opval_i[1] -- extension word
     */
    wcode[0] = ip->opval_i[0];
    wcode[1] = ip->opval_i[1] | ( operands[1].value_o<<12 );
    code_length += 2;
    eaddr( &operands[0], ip->subop_i, 0 );
}

/*
 * div_op -- long-form divide and multiply instructions that take
 * a register or register pair as operands
 */
div_op( ip )
    struct ins_bkt *ip;
{
    /* 
     * opval_i[0] -- opcode 
     * opval_i[1] -- extension word
     * opval_i[2] -- alternate extension word to be used if regpair 2nd operand
     */
    wcode[0] = ip->opval_i[0];
    if (operands[1].type_o == T_REGPAIR){
	wcode[1] = ip->opval_i[2] | (operands[1].reg_o<<12) | operands[1].value_o;
    } else {
	wcode[1] = ip->opval_i[1] | (operands[1].value_o<<12) | operands[1].value_o;
    }
    code_length += 2;
    eaddr( &operands[0], SUBOP_L, 0 );
}

/* callm_op -- process the callm instruction */
callm_op( ip )
    struct ins_bkt *ip;
{
    wcode[0] = ip->opval_i[0];
    wcode[1] = operands[0].value_o;
    code_length += 2;
    eaddr( &operands[1], SUBOP_L, 0 );
}

/*
 * cas1_op -- stupid comapare & set.
 */
cas1_op( ip )
    struct ins_bkt *ip;
{
    wcode[0] = ip->opval_i[0];
    wcode[1] = (operands[1].value_o<<6) + (operands[0].value_o);
    code_length += 2;
    eaddr( &operands[2], ip->subop_i, 1);
}

/*
 * cas2_op -- stupid comapare & set.
 */
cas2_op( ip )
    struct ins_bkt *ip;
{
    register struct oper * op = &operands[0];
    wcode[0] = ip->opval_i[0];
    wcode[1] = (op[2].value_o<<12) + (op[1].value_o<<6) + (op[0].value_o);
    wcode[2] = (op[2].reg_o<<12) + (op[1].reg_o<<6) + (op[0].reg_o);
    code_length += 4;
}

/*
 * pack_op -- the ridiculous bcd pack instruction.
 */
pack_op( ip )
    struct ins_bkt *ip;
{
    wcode[0] = ip->opval_i[0] | ((operands[0].type_o==T_REG)?0 : (1<<3));
    wcode[0] |= operands[0].value_o&07 | ((operands[1].value_o&07)<<9);
    rel_val( &operands[2], SUBOP_W, 0);
}

unix.superglobalmegacorp.com

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