- /* if division by self then 1 */
- if (IC_LEFT(ic)->key == IC_RIGHT(ic)->key) {
- ic->op = '=';
- IC_RIGHT(ic) = operandFromLit(1);
- IC_LEFT(ic) = NULL;
- IC_RESULT(ic) = operandFromOperand(IC_RESULT(ic));
- IC_RESULT(ic)->isaddr = 0;
- }
- /* if this is a division then check if right */
- /* is one then change it to an assignment */
- if (IS_OP_LITERAL(IC_RIGHT(ic)) &&
- operandLitValue(IC_RIGHT(ic)) == 1.0 ) {
-
- ic->op = '=' ;
- IC_RIGHT(ic) = IC_LEFT(ic);
- IC_LEFT(ic) = NULL;
- SET_RESULT_RIGHT(ic);
- return ;
- }
- break;
- /* if both are the same for an comparison operators */
- case EQ_OP :
- case LE_OP :
- case GE_OP :
- if (isOperandEqual(IC_LEFT(ic),IC_RIGHT(ic))) {
- ic->op = '=';
- IC_RIGHT(ic) = operandFromLit(1);
- IC_LEFT(ic) = NULL;
- SET_RESULT_RIGHT(ic);
- }
- break;
- case NE_OP :
- case '>' :
- case '<' :
- if (isOperandEqual(IC_LEFT(ic),IC_RIGHT(ic))) {
- ic->op = '=';
- IC_RIGHT(ic) = operandFromLit(0);
- IC_LEFT(ic) = NULL ;
- SET_RESULT_RIGHT(ic);
- }
- break ;
- case CAST :
- /* if this is a cast of a literal value */
- if ( IS_OP_LITERAL(IC_RIGHT(ic))) {
- ic->op = '=' ;
- IC_RIGHT(ic) =
- operandFromValue (valCastLiteral(operandType(IC_LEFT(ic)),
- operandLitValue(IC_RIGHT(ic))));
- IC_LEFT(ic) = NULL;
- SET_ISADDR(IC_RESULT(ic),0);
- }
- /* if casting to the same */
- if ( checkType(operandType(IC_RESULT(ic)),
- operandType(IC_RIGHT(ic))) == 1) {
- ic->op = '=';
- IC_LEFT(ic) = NULL;
- SET_ISADDR(IC_RESULT(ic),0);
- }
- break;
- case '!' :
- if (IS_OP_LITERAL(IC_LEFT(ic))) {
- ic->op = '=' ;
- IC_RIGHT(ic) =
- (operandLitValue(IC_LEFT(ic)) == 0 ?
- operandFromLit(1) : operandFromLit(0));
- IC_LEFT(ic) = NULL;
- SET_ISADDR(IC_RESULT(ic),0);
- }
+ /* if division by self then 1 */
+ if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key)
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromLit (1);
+ IC_LEFT (ic) = NULL;
+ IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
+ IC_RESULT (ic)->isaddr = 0;
+ return;
+ }
+ /* if this is a division then check if left is zero */
+ /* and right is not then change it to an assignment */
+ if (IS_OP_LITERAL (IC_LEFT (ic)) && IS_OP_LITERAL (IC_RIGHT (ic)) &&
+ (operandLitValue (IC_LEFT (ic)) == 0.0) && (operandLitValue (IC_RIGHT (ic)) != 0.0))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ /* if this is a division then check if right */
+ /* is one then change it to an assignment */
+ if (IS_OP_LITERAL (IC_RIGHT (ic)))
+ {
+ double rightValue = operandLitValue (IC_RIGHT (ic));
+ if (rightValue == 1.0)
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ if (rightValue == -1.0)
+ {
+ /* '/' can have two unsigned chars as operands */
+ /* and an unsigned int as result. */
+ if (IS_INTEGRAL (operandType (IC_LEFT (ic))))
+ {
+ if ((getSize (operandType (IC_LEFT (ic))) < (unsigned int) INTSIZE) &&
+ (getSize (operandType (IC_LEFT (ic))) < getSize (operandType (IC_RESULT (ic)))))
+ {
+ operand * op;
+ iCode * newic;
+ /* Widen to int. */
+ op = operandFromOperand (IC_RESULT (ic));
+ op->type = TYPE;
+ setOperandType (op, INTTYPE);
+ newic = newiCode (CAST, op, IC_LEFT (ic));
+ IC_RESULT (newic) = newiTempOperand (INTTYPE, TRUE);
+ addiCodeToeBBlock (ebp, newic, ic);
+ IC_LEFT (ic) = IC_RESULT (newic);
+ }
+ }
+ /* convert x / -1 to -x */
+ ic->op = UNARYMINUS;
+ IC_RIGHT (ic) = NULL;
+ return;
+ }
+ }
+ break;
+ /* if both are the same for an comparison operators */
+ case EQ_OP:
+ case LE_OP:
+ case GE_OP:
+ if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromLit (1);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ }
+ break;
+ case NE_OP:
+ case '>':
+ case '<':
+ if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromLit (0);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ }
+ break;
+ case CAST:
+ {
+ sym_link *otype = operandType(IC_RIGHT(ic));
+ sym_link *ctype = operandType(IC_LEFT(ic));
+ /* if this is a cast of a literal value */
+ if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
+ !(IS_GENPTR(ctype) && (IS_PTR(otype) && !IS_GENPTR(otype))))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromValue (valCastLiteral (operandType (IC_LEFT (ic)),
+ operandLitValue (IC_RIGHT (ic))));
+ IC_LEFT (ic) = NULL;
+ SET_ISADDR (IC_RESULT (ic), 0);
+ }
+ /* if casting to the same */
+ if (compareType (operandType (IC_RESULT (ic)), operandType (IC_RIGHT (ic))) == 1)
+ {
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_ISADDR (IC_RESULT (ic), 0);
+ }
+ }
+ break;
+ case '!':
+ if (IS_OP_LITERAL (IC_LEFT (ic)))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) =
+ (operandLitValue (IC_LEFT (ic)) == 0 ?
+ operandFromLit (1) : operandFromLit (0));
+ IC_LEFT (ic) = NULL;
+ SET_ISADDR (IC_RESULT (ic), 0);
+ }
+ break;
+ case BITWISEAND:
+ /* if both operands are equal */
+ /* if yes turn it into assignment */
+ if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+ {
+ if (IS_OP_VOLATILE (IC_LEFT (ic)))
+ {
+ iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+ IC_RESULT (newic) = IC_LEFT (ic);
+ newic->filename = ic->filename;
+ newic->lineno = ic->lineno;
+ addiCodeToeBBlock (ebp, newic, ic->next);
+ }
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ /* swap literal to right ic */
+ if (IS_OP_LITERAL (IC_LEFT (ic)))
+ {
+ operand *op;
+
+ op = IC_LEFT (ic);
+ IC_LEFT (ic) = IC_RIGHT (ic);
+ IC_RIGHT (ic) = op;
+ }
+ if (IS_OP_LITERAL (IC_RIGHT (ic)))
+ {
+ /* if BITWISEAND then check if one of them is a zero */
+ /* if yes turn it into 0 assignment */
+ if (operandLitValue (IC_RIGHT (ic)) == 0.0)
+ {
+ if (IS_OP_VOLATILE (IC_LEFT (ic)))
+ {
+ iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+ IC_RESULT (newic) = IC_LEFT (ic);
+ newic->filename = ic->filename;
+ newic->lineno = ic->lineno;
+ addiCodeToeBBlock (ebp, newic, ic->next);
+ }
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ /* if BITWISEAND then check if one of them is 0xff... */
+ /* if yes turn it into assignment */
+ {
+ unsigned val;
+
+ switch (getSize (operandType (IC_RIGHT (ic))))
+ {
+ case 1:
+ val = 0xff;
+ break;
+ case 2:
+ val = 0xffff;
+ break;
+ case 4:
+ val = 0xffffffff;
+ break;
+ default:
+ return;
+ }
+ if (((unsigned) double2ul (operandLitValue (IC_RIGHT (ic))) & val) == val)
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ }
+ }
+ break;
+ case '|':
+ /* if both operands are equal */
+ /* if yes turn it into assignment */
+ if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+ {
+ if (IS_OP_VOLATILE (IC_LEFT (ic)))
+ {
+ iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+ IC_RESULT (newic) = IC_LEFT (ic);
+ newic->filename = ic->filename;
+ newic->lineno = ic->lineno;
+ addiCodeToeBBlock (ebp, newic, ic->next);
+ }
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ /* swap literal to right ic */
+ if (IS_OP_LITERAL (IC_LEFT (ic)))
+ {
+ operand *op;
+
+ op = IC_LEFT (ic);
+ IC_LEFT (ic) = IC_RIGHT (ic);
+ IC_RIGHT (ic) = op;
+ }
+ if (IS_OP_LITERAL (IC_RIGHT (ic)))
+ {
+ /* if BITWISEOR then check if one of them is a zero */
+ /* if yes turn it into assignment */
+ if (operandLitValue (IC_RIGHT (ic)) == 0.0)
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ /* if BITWISEOR then check if one of them is 0xff... */
+ /* if yes turn it into 0xff... assignment */
+ {
+ unsigned val;
+
+ switch (getSize (operandType (IC_RIGHT (ic))))
+ {
+ case 1:
+ val = 0xff;
+ break;
+ case 2:
+ val = 0xffff;
+ break;
+ case 4:
+ val = 0xffffffff;
+ break;
+ default:
+ return;
+ }
+ if (((unsigned) double2ul (operandLitValue (IC_RIGHT (ic))) & val) == val)
+ {
+ if (IS_OP_VOLATILE (IC_LEFT (ic)))
+ {
+ iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+ IC_RESULT (newic) = IC_LEFT (ic);
+ newic->filename = ic->filename;
+ newic->lineno = ic->lineno;
+ addiCodeToeBBlock (ebp, newic, ic->next);
+ }
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ }
+ }
+ break;
+ case '^':
+ /* if both operands are equal */
+ /* if yes turn it into 0 assignment */
+ if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
+ {
+ if (IS_OP_VOLATILE (IC_LEFT (ic)))
+ {
+ iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+ IC_RESULT (newic) = IC_LEFT (ic);
+ newic->filename = ic->filename;
+ newic->lineno = ic->lineno;
+ addiCodeToeBBlock (ebp, newic, ic->next);
+
+ newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic));
+ IC_RESULT (newic) = IC_LEFT (ic);
+ newic->filename = ic->filename;
+ newic->lineno = ic->lineno;
+ addiCodeToeBBlock (ebp, newic, ic->next);
+ }
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromLit (0);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ /* swap literal to right ic */
+ if (IS_OP_LITERAL (IC_LEFT (ic)))
+ {
+ operand *op;
+
+ op = IC_LEFT (ic);
+ IC_LEFT (ic) = IC_RIGHT (ic);
+ IC_RIGHT (ic) = op;
+ }
+ /* if XOR then check if one of them is a zero */
+ /* if yes turn it into assignment */
+ if (IS_OP_LITERAL (IC_RIGHT (ic)))
+ {
+ if (operandLitValue (IC_RIGHT (ic)) == 0.0)
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ }
+ break;