+ sym_link *let , *ret=NULL;
+ operand *retval = (operand *) 0;
+
+ assert (isOperandLiteral (left));
+ let = getSpec(operandType(left));
+ if (right) {
+ assert (isOperandLiteral (right));
+ ret = getSpec(operandType(right));
+ }
+
+ switch (op)
+ {
+ case '+':
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) +
+ operandLitValue (right)));
+ break;
+ case '-':
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) -
+ operandLitValue (right)));
+ break;
+ case '*':
+ /*
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) *
+ operandLitValue (right)));
+ This could be all we've to do, but with gcc we've to take care about
+ overflows. Two examples:
+ ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
+ significant bits are lost (52 in fraction, 63 bits would be
+ necessary to keep full precision).
+ If the resulting double value is greater than ULONG_MAX (resp.
+ USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
+ */
+
+ /* if it is not a specifier then we can assume that */
+ /* it will be an unsigned long */
+ if (IS_INT (type) ||
+ !IS_SPEC (type))
+ {
+ /* long is handled here, because it can overflow with double */
+ if (IS_LONG (type) ||
+ !IS_SPEC (type))
+ /* signed and unsigned mul are the same, as long as the precision
+ of the result isn't bigger than the precision of the operands. */
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD) operandLitValue (left) *
+ (TYPE_UDWORD) operandLitValue (right)));
+ else if (IS_UNSIGNED (type)) /* unsigned int */
+ {
+ /* unsigned int is handled here in order to detect overflow */
+ TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
+ (TYPE_UWORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
+ if (ul != (TYPE_UWORD) ul)
+ werror (W_INT_OVL);
+ }
+ else /* signed int */
+ {
+ /* signed int is handled here in order to detect overflow */
+ TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
+ (TYPE_WORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
+ if (l != (TYPE_WORD) l)
+ werror (W_INT_OVL);
+ }
+ }
+ else
+ /* all others go here: */
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) *
+ operandLitValue (right)));
+ break;
+ case '/':
+ if ((TYPE_UDWORD) operandLitValue (right) == 0)
+ {
+ werror (E_DIVIDE_BY_ZERO);
+ retval = right;
+
+ }
+ else
+ {
+ if (IS_UNSIGNED (type))
+ {
+ SPEC_USIGN (let) = 1;
+ SPEC_USIGN (ret) = 1;
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD) operandLitValue (left) /
+ (TYPE_UDWORD) operandLitValue (right)));
+ }
+ else
+ {
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) /
+ operandLitValue (right)));
+ }
+ }
+ break;
+ case '%':
+ if ((TYPE_UDWORD) operandLitValue (right) == 0)
+ {
+ werror (E_DIVIDE_BY_ZERO);
+ retval = right;
+ }
+ else
+ {
+ if (IS_UNSIGNED (type))
+ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
+ (TYPE_UDWORD) operandLitValue (right));
+ else
+ retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
+ (TYPE_DWORD) operandLitValue (right));
+ }
+ break;
+ case LEFT_OP:
+ /* The number of left shifts is always unsigned. Signed doesn't make
+ sense here. Shifting by a negative number is impossible. */
+ retval = operandFromValue (valCastLiteral (type,
+ ((TYPE_UDWORD) operandLitValue (left) <<
+ (TYPE_UDWORD) operandLitValue (right))));
+ break;
+ case RIGHT_OP:
+ /* The number of right shifts is always unsigned. Signed doesn't make
+ sense here. Shifting by a negative number is impossible. */
+ if (IS_UNSIGNED(let))
+ /* unsigned: logic shift right */
+ retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
+ (TYPE_UDWORD) operandLitValue (right));
+ else
+ /* signed: arithmetic shift right */
+ retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
+ (TYPE_UDWORD) operandLitValue (right));
+ break;
+ case EQ_OP:
+ /* this op doesn't care about signedness */
+ {
+ TYPE_UDWORD l, r;
+
+ l = (TYPE_UDWORD) operandLitValue (left);
+ if (IS_CHAR(OP_VALUE(left)->type))
+ l &= 0xff;
+ else if (!IS_LONG (OP_VALUE(left)->type))
+ l &= 0xffff;
+ r = (TYPE_UDWORD) operandLitValue (right);
+ if (IS_CHAR(OP_VALUE(right)->type))
+ r &= 0xff;
+ else if (!IS_LONG (OP_VALUE(right)->type))
+ r &= 0xffff;
+ retval = operandFromLit (l == r);
+ }
+ break;
+ case '<':
+ retval = operandFromLit (operandLitValue (left) <
+ operandLitValue (right));
+ break;
+ case LE_OP:
+ retval = operandFromLit (operandLitValue (left) <=
+ operandLitValue (right));
+ break;
+ case NE_OP:
+ retval = operandFromLit (operandLitValue (left) !=
+ operandLitValue (right));
+ break;
+ case '>':
+ retval = operandFromLit (operandLitValue (left) >
+ operandLitValue (right));
+ break;
+ case GE_OP:
+ retval = operandFromLit (operandLitValue (left) >=
+ operandLitValue (right));
+ break;
+ case BITWISEAND:
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) &
+ (TYPE_UDWORD)operandLitValue(right)));
+ break;
+ case '|':
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) |
+ (TYPE_UDWORD)operandLitValue(right)));
+ break;
+ case '^':
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD)operandLitValue(left) ^
+ (TYPE_UDWORD)operandLitValue(right)));
+ break;
+ case AND_OP:
+ retval = operandFromLit (operandLitValue (left) &&
+ operandLitValue (right));
+ break;
+ case OR_OP:
+ retval = operandFromLit (operandLitValue (left) ||
+ operandLitValue (right));
+ break;
+ case RRC:
+ {
+ TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
+
+ retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
+ (i << 1));
+ }
+ break;
+ case RLC:
+ {
+ TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
+
+ retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
+ (i >> 1));
+ }
+ break;
+
+ case UNARYMINUS:
+ retval = operandFromValue (valCastLiteral (type,
+ -1 * operandLitValue (left)));
+ break;
+
+ case '~':
+ retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
+ break;
+
+ case '!':
+ retval = operandFromLit (!operandLitValue (left));
+ break;
+
+ default:
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ " operandOperation invalid operator ");
+ assert (0);
+ }
+
+ return retval;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* isOperandEqual - compares two operand & return 1 if they r = */
+/*-----------------------------------------------------------------*/
+int
+isOperandEqual (operand * left, operand * right)
+{
+ /* if the pointers are equal then they are equal */
+ if (left == right)
+ return 1;
+
+ /* if either of them null then false */
+ if (!left || !right)
+ return 0;
+
+ if (left->type != right->type)
+ return 0;
+
+ if (IS_SYMOP (left) && IS_SYMOP (right))
+ return left->key == right->key;
+
+ /* if types are the same */
+ switch (left->type)
+ {
+ case SYMBOL:
+ return isSymbolEqual (left->operand.symOperand,
+ right->operand.symOperand);
+ case VALUE:
+ return (floatFromVal (left->operand.valOperand) ==
+ floatFromVal (right->operand.valOperand));
+ case TYPE:
+ if (compareType (left->operand.typeOperand,
+ right->operand.typeOperand) == 1)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------*/
+/* isiCodeEqual - compares two iCodes are equal, returns true if yes */
+/*-------------------------------------------------------------------*/
+int
+isiCodeEqual (iCode * left, iCode * right)
+{
+ /* if the same pointer */
+ if (left == right)
+ return 1;
+
+ /* if either of them null */
+ if (!left || !right)
+ return 0;
+
+ /* if operand are the same */
+ if (left->op == right->op)
+ {
+
+ /* compare all the elements depending on type */
+ if (left->op != IFX)
+ {
+ if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
+ return 0;
+ if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
+ return 0;
+
+ }
+ else
+ {
+ if (!isOperandEqual (IC_COND (left), IC_COND (right)))
+ return 0;
+ if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
+ return 0;
+ if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
+ return 0;
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* newiTempFromOp - create a temp Operand with same attributes */
+/*-----------------------------------------------------------------*/
+operand *
+newiTempFromOp (operand * op)
+{
+ operand *nop;
+
+ if (!op)
+ return NULL;
+
+ if (!IS_ITEMP (op))