+
+ reType = computeType (var, lit, RESULT_TYPE_NONE, op);
+
+ if (SPEC_USIGN (reType))
+ {
+ /* unsigned operation */
+ TYPE_TARGET_ULONG minValP, maxValP, minValM, maxValM;
+ TYPE_TARGET_ULONG opBitsMask = 0xffffffffu >> (32 - bitsForType (reType));
+
+ if (SPEC_USIGN (lit) && SPEC_USIGN (var))
+ {
+ /* both operands are unsigned, this is easy */
+ minValP = 0;
+ maxValP = 0xffffffffu >> (32 - varBits);
+ /* there's only range, just copy it to 2nd set */
+ minValM = minValP;
+ maxValM = maxValP;
+ }
+ else if (SPEC_USIGN (var))
+ {
+ /* lit is casted from signed to unsigned, e.g.:
+ unsigned u;
+ u == (char) -17
+ -> u == 0xffef'
+ */
+ minValP = 0;
+ maxValP = 0xffffffffu >> (32 - varBits);
+ /* there's only one range, just copy it to 2nd set */
+ minValM = minValP;
+ maxValM = maxValP;
+
+ /* it's an unsigned operation */
+ if ( IS_CHAR (reType)
+ || IS_INT (reType))
+ {
+ /* make signed literal unsigned and
+ limit no of bits to size of return type */
+ litVal = (TYPE_TARGET_ULONG) double2ul (litVal) & opBitsMask;
+ }
+ }
+ else /* SPEC_USIGN (lit) */
+ {
+ /* var is casted from signed to unsigned, e.g.:
+ signed char c;
+ c == (unsigned) -17
+ -> c == 0xffef'
+
+ The possible values after casting var
+ split up in two, nonconsecutive ranges:
+
+ minValP = 0; positive range: 0...127
+ maxValP = 0x7f;
+ minValM = 0xff80; negative range: -128...-1
+ maxValM = 0xffff;
+ */
+
+ /* positive range */
+ minValP = 0;
+ maxValP = 0x7fffffffu >> (32 - varBits);
+
+ /* negative range */
+ minValM = 0xffffffff << (varBits - 1);
+ maxValM = 0xffffffffu; /* -1 */
+ /* limit no of bits to size of return type */
+ minValM &= opBitsMask;
+ maxValM &= opBitsMask;
+ }
+
+ switch (op)
+ {
+ case EQ_OP: /* var == lit */
+ if ( litVal <= maxValP
+ && litVal >= minValP) /* 0 */
+ return CCR_OK;
+ if ( litVal <= maxValM
+ && litVal >= minValM)
+ return CCR_OK;
+ return CCR_ALWAYS_FALSE;
+ case NE_OP: /* var != lit */
+ if ( litVal <= maxValP
+ && litVal >= minValP) /* 0 */
+ return CCR_OK;
+ if ( litVal <= maxValM
+ && litVal >= minValM)
+ return CCR_OK;
+ return CCR_ALWAYS_TRUE;
+ case '>': /* var > lit */
+ if (litVal >= maxValM)
+ return CCR_ALWAYS_FALSE;
+ if (litVal < minValP) /* 0 */
+ return CCR_ALWAYS_TRUE;
+ return CCR_OK;
+ case GE_OP: /* var >= lit */
+ if (litVal > maxValM)
+ return CCR_ALWAYS_FALSE;
+ if (litVal <= minValP) /* 0 */
+ return CCR_ALWAYS_TRUE;
+ return CCR_OK;
+ case '<': /* var < lit */
+ if (litVal > maxValM)
+ return CCR_ALWAYS_TRUE;
+ if (litVal <= minValP) /* 0 */
+ return CCR_ALWAYS_FALSE;
+ return CCR_OK;
+ case LE_OP: /* var <= lit */
+ if (litVal >= maxValM)
+ return CCR_ALWAYS_TRUE;
+ if (litVal < minValP) /* 0 */
+ return CCR_ALWAYS_FALSE;
+ return CCR_OK;
+ default:
+ return CCR_ALWAYS_FALSE;
+ }
+ }
+ else
+ {
+ /* signed operation */
+ TYPE_TARGET_LONG minVal, maxVal;
+
+ if (SPEC_USIGN (var))
+ {
+ /* unsigned var, but signed operation. This happens
+ when var is promoted to signed int.
+ Set actual min/max values of var. */
+ minVal = 0;
+ maxVal = 0xffffffff >> (32 - varBits);
+ }
+ else
+ {
+ /* signed var */
+ minVal = 0xffffffff << (varBits - 1);
+ maxVal = 0x7fffffff >> (32 - varBits);
+ }
+
+ switch (op)
+ {
+ case EQ_OP: /* var == lit */
+ if ( litVal > maxVal
+ || litVal < minVal)
+ return CCR_ALWAYS_FALSE;
+ return CCR_OK;
+ case NE_OP: /* var != lit */
+ if ( litVal > maxVal
+ || litVal < minVal)
+ return CCR_ALWAYS_TRUE;
+ return CCR_OK;
+ case '>': /* var > lit */
+ if (litVal >= maxVal)
+ return CCR_ALWAYS_FALSE;
+ if (litVal < minVal)
+ return CCR_ALWAYS_TRUE;
+ return CCR_OK;
+ case GE_OP: /* var >= lit */
+ if (litVal > maxVal)
+ return CCR_ALWAYS_FALSE;
+ if (litVal <= minVal)
+ return CCR_ALWAYS_TRUE;
+ return CCR_OK;
+ case '<': /* var < lit */
+ if (litVal > maxVal)
+ return CCR_ALWAYS_TRUE;
+ if (litVal <= minVal)
+ return CCR_ALWAYS_FALSE;
+ return CCR_OK;
+ case LE_OP: /* var <= lit */
+ if (litVal >= maxVal)
+ return CCR_ALWAYS_TRUE;
+ if (litVal < minVal)
+ return CCR_ALWAYS_FALSE;
+ return CCR_OK;
+ default:
+ return CCR_ALWAYS_FALSE;
+ }