/* 
   Copyright 1994-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
/*
 * 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)
{
   return make_immed(val) ;
}
void badconst(void)
{
	DIAG("ICODE- Bad constant node");
}
int calshift(LLONG_TYPE i)
/*
 *      return which power of two i is or -1.
 */
{       LLONG_TYPE     q;
        int p ;
        q = 2;
        p = 1;
        while( q > 0 )
                {
                if( q == i )
                        return p;
                q <<= 1;
                ++p;
                }
        return -1;
}

LLONG_TYPE     calmod(int i)
/*
 *      make a mod mask for a power of two.
 */
{       LLONG_TYPE     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 0:
               if (d->dc.left == d->dc.right) {
                     d->dc.opcode = i_smul ;
                     d->livein |= IM_LIVERIGHT ;
                     d->dc.right = intconst(2) ;
               }
               break ;
				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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
				case 8:
					if (right->f == 0) {
						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 0:
               if (d->dc.left == d->dc.right) {
                     d->dc.opcode = i_icon ;
                     d->livein |= IM_LIVELEFT ;
                     d->dc.v.i = intconst(0) ;
               }
               break ;
				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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
				case 8:
					if (right->f == 0) {
						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)) != -1) {
						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.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_LIVELEFT | 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_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;
				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)) != -1) {
						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.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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
               else if ((shift = calshift((unsigned)left->i)) != -1) {
						d->dc.left = d->dc.right;
						d->dc.right = intconst(shift);
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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)) != -1) {
						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 = 0;
                  d->dc.v.f = 0;
                  d->livein |= IM_LIVELEFT | IM_LIVERIGHT;
                  d->dc.opcode = i_fcon;
					}
					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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     d->livein |= IM_LIVERIGHT;
						d->dc.opcode = i_assn;
					}
               else if ((shift = calshift(left->i)) != -1) {
						d->dc.left = d->dc.right;
						d->dc.right = intconst(shift);
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     d->livein |= IM_LIVERIGHT;
						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)) != -1) {
						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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
                  if (d->livein & IM_LIVERIGHT)
                     d->livein |= IM_LIVELEFT ;
                  else 
                     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;
	}
}