/*-----------------------------------------------------------------*/
/* forward definition of some functions */
-operand *geniCodeDivision (operand *, operand *, bool);
operand *geniCodeAssign (operand *, operand *, int);
static operand *geniCodeArray (operand *, operand *,int);
static operand *geniCodeArray2Ptr (operand *);
(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);
- }
+ if (IS_FLOAT (let) ||
+ IS_FLOAT (ret))
+ {
+ retval = operandFromLit (operandLitValue (left) ==
+ operandLitValue (right));
+ }
+ else
+ {
+ /* this op doesn't care about signedness */
+ TYPE_UDWORD l, r;
+
+ l = (TYPE_UDWORD) operandLitValue (left);
+ r = (TYPE_UDWORD) operandLitValue (right);
+ /* In order to correctly compare 'signed int' and 'unsigned int' it's
+ neccessary to strip them to 16 bit.
+ Literals are reduced to their cheapest type, therefore left and
+ right might have different types. It's neccessary to find a
+ common type: int (used for char too) or long */
+ if (!IS_LONG (let) &&
+ !IS_LONG (ret))
+ {
+ r = (TYPE_UWORD) r;
+ l = (TYPE_UWORD) l;
+ }
+ retval = operandFromLit (l == r);
+ }
break;
case '<':
retval = operandFromLit (operandLitValue (left) <
}
}
+
/*-----------------------------------------------------------------*/
/* Get size in byte of ptr need to access an array */
/*-----------------------------------------------------------------*/
-int
+static int
getArraySizePtr (operand * op)
{
sym_link *ltype = operandType(op);
static sym_link *
usualBinaryConversions (operand ** op1, operand ** op2,
- bool resultIsInt, char op)
+ RESULT_TYPE resultType, int op)
{
sym_link *ctype;
sym_link *rtype = operandType (*op2);
sym_link *ltype = operandType (*op1);
-#define OLDONEBYTEOPS 1
-
-#ifdef OLDONEBYTEOPS
- bool oldOneByteOps = FALSE;
- static bool saidHello = FALSE;
-
- if (strcmp (port->target, "pic14") == 0)
- oldOneByteOps = TRUE;
- if (getenv ("SDCC_NEWONEBYTEOPS"))
- {
- if (!saidHello)
- {
- fprintf (stderr, "Override: oldOneByteOps = FALSE\n");
- saidHello = TRUE;
- }
- oldOneByteOps = FALSE;
- }
- else if (getenv ("SDCC_OLDONEBYTEOPS"))
- {
- if (!saidHello)
- {
- fprintf (stderr, "Override: oldOneByteOps = TRUE\n");
- saidHello = TRUE;
- }
- oldOneByteOps = TRUE;
- }
-
-
- if ( oldOneByteOps
- && ( (IS_CHAR (getSpec (ltype)) && !IS_UNSIGNED (getSpec (ltype)))
- || (IS_CHAR (getSpec (rtype)) && !IS_UNSIGNED (getSpec (rtype)))))
- /* one or two signed char operands: promote to int */
- resultIsInt = TRUE;
-#endif
-
- ctype = computeType (ltype, rtype, resultIsInt);
-
-#ifdef OLDONEBYTEOPS
-
- if (oldOneByteOps)
- {
- if ( op == '*'
- && IS_CHAR (getSpec (ltype)) && IS_UNSIGNED (getSpec (ltype))
- && IS_CHAR (getSpec (rtype)) && IS_UNSIGNED (getSpec (rtype)))
- {
- /* two unsigned char operands and Mult: no promotion */
- return ctype;
- }
- *op1 = geniCodeCast (ctype, *op1, TRUE);
- *op2 = geniCodeCast (ctype, *op2, TRUE);
-
- return ctype;
- }
-
-#endif
+ ctype = computeType (ltype, rtype, resultType, op);
switch (op)
{
/* preserve the storage class & output class */
/* of the original variable */
restype = getSpec (operandType (IC_RESULT (ic)));
- if (!IS_LITERAL(opetype))
+ if (!IS_LITERAL(opetype) &&
+ !IS_BIT(opetype))
SPEC_SCLS (restype) = SPEC_SCLS (opetype);
SPEC_OCLS (restype) = SPEC_OCLS (opetype);
/*-----------------------------------------------------------------*/
/* geniCodeMultiply - gen intermediate code for multiplication */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeMultiply (operand * left, operand * right, bool resultIsInt)
+static operand *
+geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int p2 = 0;
p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
}
- resType = usualBinaryConversions (&left, &right, resultIsInt, '*');
+ resType = usualBinaryConversions (&left, &right, resultType, '*');
#if 1
rtype = operandType (right);
retype = getSpec (rtype);
efficient in most cases than 2 bytes result = 2 bytes << literal
if port has 1 byte muldiv */
if (p2 && !IS_FLOAT (letype)
- && !((resultIsInt) && (getSize (resType) != getSize (ltype))
+ && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
&& (port->support.muldiv == 1))
&& strcmp (port->target, "pic14") != 0 /* don't shift for pic */
&& strcmp (port->target, "pic16") != 0)
{
- if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
+ if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
{
/* LEFT_OP need same size for left and result, */
left = geniCodeCast (resType, left, TRUE);
/*-----------------------------------------------------------------*/
/* geniCodeDivision - gen intermediate code for division */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeDivision (operand * left, operand * right, bool resultIsInt)
+static operand *
+geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int p2 = 0;
sym_link *ltype = operandType (left);
sym_link *letype = getSpec (ltype);
- resType = usualBinaryConversions (&left, &right, resultIsInt, '/');
+ resType = usualBinaryConversions (&left, &right, resultType, '/');
/* if the right is a literal & power of 2
and left is unsigned then make it a
/*-----------------------------------------------------------------*/
/* geniCodeModulus - gen intermediate code for modulus */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeModulus (operand * left, operand * right, bool resultIsInt)
+static operand *
+geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
sym_link *resType;
return operandFromValue (valMod (left->operand.valOperand,
right->operand.valOperand));
- resType = usualBinaryConversions (&left, &right, resultIsInt, '%');
+ resType = usualBinaryConversions (&left, &right, resultType, '%');
/* now they are the same size */
ic = newiCode ('%', left, right);
/*-----------------------------------------------------------------*/
/* geniCodeSubtract - generates code for subtraction */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeSubtract (operand * left, operand * right)
+static operand *
+geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
int isarray = 0;
{
isarray = left->isaddr;
right = geniCodeMultiply (right,
- operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+ operandFromLit (getSize (ltype->next)),
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
}
else
{ /* make them the same size */
- resType = usualBinaryConversions (&left, &right, FALSE, '-');
+ resType = usualBinaryConversions (&left, &right, resultType, '-');
}
ic = newiCode ('-', left, right);
/*-----------------------------------------------------------------*/
/* geniCodeAdd - generates iCode for addition */
/*-----------------------------------------------------------------*/
-operand *
-geniCodeAdd (operand * left, operand * right, int lvl)
+static operand *
+geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
{
iCode *ic;
sym_link *resType;
size = operandFromLit (getSize (ltype->next));
SPEC_USIGN (getSpec (operandType (size))) = 1;
indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
- right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
+ right = geniCodeMultiply (right,
+ size,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
/* Even if right is a 'unsigned char',
the result will be a 'signed int' due to the promotion rules.
It doesn't make sense when accessing arrays, so let's fix it here: */
}
else
{ // make them the same size
- resType = usualBinaryConversions (&left, &right, FALSE, '+');
+ resType = usualBinaryConversions (&left, &right, resultType, '+');
}
/* if they are both literals then we know */
left = geniCodeRValue (left, FALSE);
}
- return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
+ return geniCodeDerefPtr (geniCodeAdd (left,
+ right,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR,
+ lvl),
+ lvl);
}
size = operandFromLit (getSize (ltype->next));
SPEC_USIGN (getSpec (operandType (size))) = 1;
indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
- right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
+ right = geniCodeMultiply (right,
+ size,
+ (getArraySizePtr(left) >= INTSIZE) ?
+ RESULT_TYPE_INT :
+ RESULT_TYPE_CHAR);
/* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
It doesn't make sense when accessing arrays, so let's fix it here: */
if (indexUnsigned)
/* geniCodeLeftShift - gen i code for left shift */
/*-----------------------------------------------------------------*/
operand *
-geniCodeLeftShift (operand * left, operand * right)
+geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
{
iCode *ic;
+ sym_link *resType;
ic = newiCode (LEFT_OP, left, right);
- IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
+
+ resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
+ IC_RESULT (ic) = newiTempOperand (resType, 0);
ADDTOCHAIN (ic);
return IC_RESULT (ic);
}
}
}
- ctype = usualBinaryConversions (&left, &right, FALSE, ' ');
+ ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
ic = newiCode (op, left, right);
IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
/* if the min is not zero then we no make it zero */
if (min)
{
- cond = geniCodeSubtract (cond, operandFromLit (min));
+ cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
if (!IS_LITERAL(getSpec(operandType(cond))))
setOperandType (cond, UCHARTYPE);
}
case '/':
return geniCodeDivision (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),
- IS_INT (tree->ftype));
+ getResultTypeFromType (tree->ftype));
case '%':
return geniCodeModulus (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),
- IS_INT (tree->ftype));
+ getResultTypeFromType (tree->ftype));
case '*':
if (right)
return geniCodeMultiply (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE),
- IS_INT (tree->ftype));
+ getResultTypeFromType (tree->ftype));
else
return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
case '-':
if (right)
return geniCodeSubtract (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
else
return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
case '+':
if (right)
return geniCodeAdd (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE),lvl);
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype),
+ lvl);
else
return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
case LEFT_OP:
return geniCodeLeftShift (geniCodeRValue (left, FALSE),
- geniCodeRValue (right, FALSE));
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype));
case RIGHT_OP:
return geniCodeRightShift (geniCodeRValue (left, FALSE),
geniCodeAssign (left,
geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
FALSE),
- geniCodeRValue (right, FALSE),FALSE), 0);
+ geniCodeRValue (right, FALSE), FALSE),
+ getResultTypeFromType (tree->ftype));
case DIV_ASSIGN:
return
geniCodeDivision (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE),
- IS_INT (tree->ftype)),
+ getResultTypeFromType (tree->ftype)),
0);
case MOD_ASSIGN:
return
geniCodeModulus (geniCodeRValue (operandFromOperand (left),
FALSE),
geniCodeRValue (right, FALSE),
- IS_INT (tree->ftype)),
+ getResultTypeFromType (tree->ftype)),
0);
case ADD_ASSIGN:
{
return geniCodeAssign (left,
geniCodeAdd (geniCodeRValue (operandFromOperand (left),
FALSE),
- right,lvl), 0);
+ right,
+ getResultTypeFromType (tree->ftype),
+ lvl),
+ 0);
}
case SUB_ASSIGN:
{
geniCodeAssign (left,
geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
FALSE),
- right), 0);
+ right,
+ getResultTypeFromType (tree->ftype)),
+ 0);
}
case LEFT_ASSIGN:
return
geniCodeAssign (left,
geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
,FALSE),
- geniCodeRValue (right, FALSE)), 0);
+ geniCodeRValue (right, FALSE),
+ getResultTypeFromType (tree->ftype)),
+ 0);
case RIGHT_ASSIGN:
return
geniCodeAssign (left,