/*
 * 68K/386 32-bit C compiler.
 *
 * copyright (c) 1996, David Lindauer
 * 
 * This compiler is intended for educational use.  It may not be used
 * for profit without the express written consent of the author.
 *
 * It may be freely redistributed, as long as this notice remains intact
 * and sources are distributed along with any executables derived from them.
 *
 * The author is not responsible for damages, either direct or consequential,
 * that may arise from use of this software.
 *
 * V2.05 June 2002
 * David Lindauer, gclind01@starbase.spd.louisville.edu
 *
 * Credits to Mathew Brandt for original K&R C compiler
 *
 */
/*
 * iconst.c
 *
 * Constant folding.  Is done at the same time as CSEs.
 *
 */
#include        <stdio.h>
#include				<malloc.h>
#include 				<string.h>
#include				"utype.h"	
#include				"cmdline.h"	
#include        "lists.h"
#include        "expr.h"
#include        "c.h"
#include				"iexpr.h"
#include				"iopt.h"
#include				"diag.h"

extern int prm_foldconst;
extern **name_hash;

IMODE *intconst(long val)
{
	IMODE *rv = tempreg(-4,0);
	QUAD *inter;
	gen_iiconst(rv,val);
	inter = LookupNVHash(&rv,sizeof(void *),name_hash);
	if (inter)
		return inter->ans;
	return rv;
}
void badconst(void)
{
	DIAG("ICODE- Bad constant node");
}
long     calshift(long i)
/*
 *      return which power of two i is or -1.
 */
{       long     p, q;
        q = 2;
        p = 1;
        while( q > 0 )
                {
                if( q == i )
                        return p;
                q <<= 1;
                ++p;
                }
        return -1;
}

long     calmod(long i)
/*
 *      make a mod mask for a power of two.
 */
{       long     m;
        m = 0;
        while( i-- )
                m = (m << 1) | 1;
        return m;
}
/*
 * when we get here the quad node will have node replacements
 * for named nodes done.  Constants will always have been replaced
 * from the named node describing the constant at this point.
 * If either or both of the
 * node arguments are constants the QUAD left and or right pointers
 * will point to QUAD nodes describing the constants and the
 * appropriate bits in the livein member of the quad will be clear
 */
static int xgetmode(QUAD *d, struct ival **left, struct ival **right)
/*
 * get the constant mode of a pair of nodes
 * 0 = Neither node is a constant
 * 1 = icon,icon
 * 2 = icon,rcon
 * 3 = rcon,icon
 * 4 = rcon,rcon
 * 5 = icon,nothing
 * 6 = rcon,nothing
 * 7 = nothing,icon
 * 8 = nothing,rcon
 */
{
				int mode = 0;
				QUAD *ql = d->dc.left, *qr = d->dc.right;
				*left = *right = 0;
				if (!(d->livein & IM_LIVELEFT) && (ql && ql->dc.opcode == i_icon || ql->dc.opcode == i_fcon))
					*left = &(ql->dc.v);
				if (!(d->livein & IM_LIVERIGHT) && (ql && qr->dc.opcode == i_icon || qr->dc.opcode == i_fcon))
					*right = &(qr->dc.v);
				if (*left && ql->dc.opcode == i_icon)
					if (right)  {
						if (qr->dc.opcode == i_icon)
							mode = 1;
						else if (qr->dc.opcode == i_fcon)
							mode = 2;
						else mode = 5;
					}
					else
						mode = 5;
				else if (*left && ql->dc.opcode == i_fcon)
					if (right)  {
						if (qr->dc.opcode == i_icon)
							mode = 3;
						else if (qr->dc.opcode == i_fcon)
							mode = 4;
						else mode = 6;
					}
					else
						mode = 6;
			  else if (*right)  {
					if (qr->dc.opcode == i_icon)
						mode = 7;
					else if (qr->dc.opcode == i_fcon)
						mode = 4;
					else mode = 8;
				}
	return(mode);
}
void ConstantFold(QUAD *d)
{
	int index,shift;
	struct ival *left=0,*right=0;
	if (!prm_foldconst)
		return;
	switch (d->dc.opcode) {
		case i_add:
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 1:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.i = left->i + right->i;
					d->dc.opcode = i_icon;
					break;
				case 2:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->i + right->f;
					d->dc.opcode = i_fcon;
					break;
				case 3:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->f + right->i;
					d->dc.opcode = i_fcon;
					break;
				case 4:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->f + right->f;
					d->dc.opcode = i_fcon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 6:
					if (left->f == 0) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.left = d->dc.left;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 8:
					if (right->f == 0) {
						d->dc.left = d->dc.left;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
			}
			break;
		case i_sub: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 1:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.i = left->i - right->i;
					d->dc.opcode = i_icon;
					break;
				case 2:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->i - right->f;
					d->dc.opcode = i_fcon;
					break;
				case 3:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->f - right->i;
					d->dc.opcode = i_fcon;
					break;
				case 4:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->f - right->f;
					d->dc.opcode = i_fcon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 6:
					if (left->f == 0) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.left = d->dc.left;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 8:
					if (right->f == 0) {
						d->dc.left = d->dc.left;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
			}
			break;
		case i_udiv: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 1:
					if ((unsigned)right->i != 0)
						d->dc.v.i = (unsigned)left->i / (unsigned)right->i;
					else d->dc.v.i = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 2:
					if (right->f != 0)
						d->dc.v.i = (unsigned)left->i / right->f;
					else d->dc.v.f = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_fcon;
					break;
				case 3:
					if ((unsigned)right->i != 0)
						d->dc.v.f = left->f / (unsigned)right->i;
					else d->dc.v.f = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_fcon;
					break;
				case 4:
					if (right->f != 0)
						d->dc.v.f = left->f / right->f;
					else d->dc.v.f = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_fcon;
					break;
				case 5:
					if ((unsigned)left->i == 0) {
						d->dc.v.i = 0;
						d->dc.opcode = i_icon;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					}
					break;
				case 6:
					if (left->f == 0) {
						d->dc.v.f = 0;
						d->dc.opcode = i_fcon;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					}
					break;
				case 7:
/* BUG!!! divide by zero = 0 */
					if ((unsigned)right->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if ((unsigned)right->i == 1) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					else if (shift = calshift((unsigned)right->i)) {
						d->dc.opcode = i_lsr;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
					}
					break;
				case 8:
					if (right->f == 0) {
						d->dc.v.f = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_fcon;
					}
					else if (right->f == 1) {
						d->dc.left = d->dc.left;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
			}
			break;
		case i_umod: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					if ((unsigned)right->i != 0)
						d->dc.v.i = (unsigned)left->i % (unsigned)right->i;
					else d->dc.v.i = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if ((unsigned)left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 7:
					if ((unsigned)right->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if (shift = calmod((unsigned)right->i)) {
						d->dc.opcode = i_and;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_sdiv: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 1:
					if (right->i != 0)
						d->dc.v.i = left->i / right->i;
					else d->dc.v.i = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 2:
					if (right->f != 0)
						d->dc.v.i = left->i / right->f;
					else d->dc.v.f = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_fcon;
					break;
				case 3:
					if (right->i != 0)
						d->dc.v.f = left->f / right->i;
					else d->dc.v.f = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_fcon;
					break;
				case 4:
					if (right->f != 0)
						d->dc.v.f = left->f / right->f;
					else d->dc.v.f = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_fcon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 6:
					if (left->f == 0) {
						d->dc.v.f = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_fcon;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if (right->i == 1) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					else if (shift = calshift(right->i)) {
						d->dc.opcode = i_lsr;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
					}
					break;
				case 8:
					if (right->f == 0) {
						d->dc.v.f = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_fcon;
					}
					else if (right->f == 1) {
						d->dc.left = d->dc.left;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
			}
			break;
		case i_smod: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					if (right->i != 0)
						d->dc.v.i = left->i % right->i;
					else d->dc.v.i = 0;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if (shift = calmod(right->i)) {
						d->dc.opcode = i_and;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
					}             
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_umul: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 1:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.i = (unsigned)left->i * (unsigned)right->i;
					d->dc.opcode = i_icon;
					break;
				case 2:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = (unsigned)left->i * (unsigned)right->f;
					d->dc.opcode = i_fcon;
					break;
				case 3:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = (unsigned)left->f * (unsigned)right->i;
					d->dc.opcode = i_fcon;
					break;
				case 4:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = (unsigned)left->f * (unsigned)right->f;
					d->dc.opcode = i_fcon;
					break;
				case 5:
					if ((unsigned)left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if ((unsigned)left->i == 1) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					else if (shift = calshift((unsigned)left->i)) {
						d->dc.left = d->dc.right;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_lsl;
					}
						
					break;
				case 6:
					if ((unsigned)left->f == 0) {
						d->dc.v.f = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_fcon;
					}
					else if ((unsigned)left->i == 1) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 7:
					if ((unsigned)right->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if ((unsigned)right->i == 1) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					else if (shift = calshift((unsigned)right->i)) {
						d->dc.opcode = i_lsl;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
					}
					break;
				case 8:
					if ((unsigned)right->f == 0) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					else if ((unsigned)right->i == 1) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
			}
			break;
		case i_smul: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 1:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.i = left->i * right->i;
					d->dc.opcode = i_icon;
					break;
				case 2:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->i * right->f;
					d->dc.opcode = i_fcon;
					break;
				case 3:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->f * right->i;
					d->dc.opcode = i_fcon;
					break;
				case 4:
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.v.f = left->f * right->f;
					d->dc.opcode = i_fcon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if (left->i == 1) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					else if (shift = calshift(left->i)) {
						d->dc.left = d->dc.right;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_lsl;
					}
						
					break;
				case 6:
					if (left->f == 0) {
						d->dc.v.f = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_fcon;
					}
					else if (left->i == 1) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					else if (right->i == 1) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					else if (shift = calshift(left->i)) {
						d->dc.opcode = i_lsl;
						d->dc.right = intconst(shift);
						d->livein |= IM_LIVERIGHT;
					}
					break;
				case 8:
					if (right->f == 0) {
						d->dc.v.f = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_fcon;
					}
					else if (right->i == 1) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
			}
			break;
		case i_lsl: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					d->dc.v.i = (unsigned)left->i << (unsigned)right->i;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_lsr: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					d->dc.v.i = (unsigned)left->i >> (unsigned)right->i;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_asl: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					d->dc.v.i = left->i << right->i;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_asr: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					d->dc.v.i = left->i >> right->i;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_and: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					d->dc.v.i = left->i & right->i;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_or: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					d->dc.v.i = left->i | right->i;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_eor:
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 1:
					d->dc.v.i = left->i ^ right->i;
					d->dc.left = d->dc.right = 0;
					d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
					d->dc.opcode = i_icon;
					break;
				case 5:
					if (left->i == 0) {
						d->dc.left = d->dc.right;
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				case 7:
					if (right->i == 0) {
						d->dc.right = 0;
						d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
					break;
				default:
					badconst();
					break;
			}
			break;
		case i_neg: 
			index = xgetmode(d,&left,&right);
			switch(index) {
				case 0:
					break;
				case 5:
					if (left->i == 0) {
						d->dc.v.i = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_icon;
					}
					break;
				case 6:
					if (left->f == 0) {
						d->dc.v.f = 0;
						d->dc.left = d->dc.right = 0;
						d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
						d->dc.opcode = i_fcon;
					}
					break;
			}
			break;
	}
}
