* sim/ucsim/configure.in,
[fw/sdcc] / src / SDCCicode.c
index f19f4129f48eae18aec872701de1bb8fa67f158b..f4e50eba162c9333a736ee99c9196b129101bc24 100644 (file)
@@ -45,10 +45,9 @@ symbol *entryLabel;          /* function entry  label */
 
 /*-----------------------------------------------------------------*/
 /* forward definition of some functions */
-operand *geniCodeDivision (operand *, operand *);
 operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *,int);
-operand *geniCodeArray2Ptr (operand *);
+static operand *geniCodeArray (operand *, operand *,int);
+static operand *geniCodeArray2Ptr (operand *);
 operand *geniCodeRValue (operand *, bool);
 operand *geniCodeDerefPtr (operand *,int);
 int isLvaluereq(int lvl);
@@ -1219,22 +1218,32 @@ operandOperation (operand * left, operand * right,
                                 (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) <
@@ -1533,6 +1542,7 @@ operandFromSymbol (symbol * sym)
          and before liveRange calculation */
       sym->reqv = newiTempOperand (sym->type, 0);
       sym->reqv->key = sym->key;
+      OP_SYMBOL (sym->reqv)->prereqv = sym;
       OP_SYMBOL (sym->reqv)->key = sym->key;
       OP_SYMBOL (sym->reqv)->isreqv = 1;
       OP_SYMBOL (sym->reqv)->islocal = 1;
@@ -1692,10 +1702,11 @@ setOperandType (operand * op, sym_link * type)
     }
 
 }
+
 /*-----------------------------------------------------------------*/
 /* Get size in byte of ptr need to access an array                 */
 /*-----------------------------------------------------------------*/
-int
+static int
 getArraySizePtr (operand * op)
 {
   sym_link *ltype = operandType(op);
@@ -1733,6 +1744,7 @@ getArraySizePtr (operand * op)
 /*-----------------------------------------------------------------*/
 /* perform "usual unary conversions"                               */
 /*-----------------------------------------------------------------*/
+#if 0
 static operand *
 usualUnaryConversions (operand * op)
 {
@@ -1746,33 +1758,94 @@ usualUnaryConversions (operand * op)
     }
   return op;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* perform "usual binary conversions"                              */
 /*-----------------------------------------------------------------*/
+
 static sym_link *
 usualBinaryConversions (operand ** op1, operand ** op2,
-                        bool promoteCharToInt, bool isMul)
+                        RESULT_TYPE resultType, char op)
 {
   sym_link *ctype;
   sym_link *rtype = operandType (*op2);
   sym_link *ltype = operandType (*op1);
 
-  ctype = computeType (ltype, rtype, promoteCharToInt);
+#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 */
+    resultType = RESULT_TYPE_INT;
+#endif
+  
+  ctype = computeType (ltype, rtype, resultType, op);
+
+#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
 
-  /* special for multiplication:
-     This if for 'mul a,b', which takes two chars and returns an int */
-  if (   isMul
-      /* && promoteCharToInt   superfluous, already handled by computeType() */
-      && IS_CHAR (getSpec (ltype))
-      && IS_CHAR (getSpec (rtype))
-      && !(IS_UNSIGNED (getSpec (rtype)) ^ IS_UNSIGNED (getSpec (ltype)))
-      && IS_INT  (getSpec (ctype)))
-    return ctype;
+  switch (op)
+    {
+      case '*':
+      case '/':
+      case '%':
+       if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
+         {
+           /* one byte operations: keep signedness for code generator */
+           return ctype;
+         }
+       break;
+      default:
+       break;
+    }
 
   *op1 = geniCodeCast (ctype, *op1, TRUE);
   *op2 = geniCodeCast (ctype, *op2, TRUE);
-
+       
   return ctype;
 }
 
@@ -1853,6 +1926,12 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
       return op;
     }
 
+  if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
+    {
+      geniCodeArray2Ptr (op);
+      op->isaddr = 0;
+    }
+    
   /* if the operand is already the desired type then do nothing */
   if (compareType (type, optype) == 1)
     return op;
@@ -1923,6 +2002,14 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
   }
 
   /* if they are the same size create an assignment */
+  
+  /* This seems very dangerous to me, since there are several */
+  /* optimizations (for example, gcse) that don't notice the  */
+  /* cast hidden in this assignement and may simplify an      */
+  /* iCode to use the original (uncasted) operand.            */
+  /* Unfortunately, other things break when this cast is      */
+  /* made explicit. Need to fix this someday.                 */
+  /* -- EEP, 2004/01/21                                       */
   if (getSize (type) == getSize (optype) &&
       !IS_BITFIELD (type) &&
       !IS_FLOAT (type) &&
@@ -1982,8 +2069,8 @@ geniCodeGoto (symbol * label)
 /*-----------------------------------------------------------------*/
 /* geniCodeMultiply - gen intermediate code for multiplication     */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeMultiply (operand * left, operand * right, int resultIsInt)
+static operand *
+geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   int p2 = 0;
@@ -1999,7 +2086,7 @@ geniCodeMultiply (operand * left, operand * right, int resultIsInt)
     p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
   }
 
-  resType = usualBinaryConversions (&left, &right, resultIsInt, TRUE);
+  resType = usualBinaryConversions (&left, &right, resultType, '*');
 #if 1
   rtype = operandType (right);
   retype = getSpec (rtype);
@@ -2012,11 +2099,13 @@ geniCodeMultiply (operand * left, operand * right, int resultIsInt)
   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
      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)) &&
-       (port->support.muldiv == 1)))
+  if (p2 && !IS_FLOAT (letype)
+      && !((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);
@@ -2041,8 +2130,8 @@ geniCodeMultiply (operand * left, operand * right, int resultIsInt)
 /*-----------------------------------------------------------------*/
 /* geniCodeDivision - gen intermediate code for division           */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeDivision (operand * left, operand * right)
+static operand *
+geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   int p2 = 0;
@@ -2052,7 +2141,7 @@ geniCodeDivision (operand * left, operand * right)
   sym_link *ltype = operandType (left);
   sym_link *letype = getSpec (ltype);
 
-  resType = usualBinaryConversions (&left, &right, TRUE, FALSE);
+  resType = usualBinaryConversions (&left, &right, resultType, '/');
 
   /* if the right is a literal & power of 2
      and left is unsigned then make it a
@@ -2079,8 +2168,8 @@ geniCodeDivision (operand * left, operand * right)
 /*-----------------------------------------------------------------*/
 /* geniCodeModulus  - gen intermediate code for modulus            */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeModulus (operand * left, operand * right)
+static operand *
+geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   sym_link *resType;
@@ -2091,7 +2180,7 @@ geniCodeModulus (operand * left, operand * right)
     return operandFromValue (valMod (left->operand.valOperand,
                                     right->operand.valOperand));
 
-  resType = usualBinaryConversions (&left, &right, TRUE, FALSE);
+  resType = usualBinaryConversions (&left, &right, resultType, '%');
 
   /* now they are the same size */
   ic = newiCode ('%', left, right);
@@ -2135,14 +2224,15 @@ subtractExit:
   
   // should we really do this? is this ANSI?
   return geniCodeDivision (result,
-                          operandFromLit (getSize (ltype->next)));
+                          operandFromLit (getSize (ltype->next)),
+                          FALSE);
 }
 
 /*-----------------------------------------------------------------*/
 /* 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;
@@ -2165,12 +2255,15 @@ geniCodeSubtract (operand * left, operand * right)
     {
       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, FALSE);
+      resType = usualBinaryConversions (&left, &right, resultType, '-');
     }
 
   ic = newiCode ('-', left, right);
@@ -2189,8 +2282,8 @@ geniCodeSubtract (operand * left, operand * 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;
@@ -2216,8 +2309,13 @@ geniCodeAdd (operand * left, operand * right, int lvl)
       if (getSize (ltype->next) != 1)
         {
          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: */
@@ -2228,7 +2326,7 @@ geniCodeAdd (operand * left, operand * right, int lvl)
     }
   else
     { // make them the same size
-      resType = usualBinaryConversions (&left, &right, FALSE, FALSE);
+      resType = usualBinaryConversions (&left, &right, resultType, '+');
     }
 
   /* if they are both literals then we know */
@@ -2278,7 +2376,7 @@ aggrToPtr (sym_link * type, bool force)
 /*-----------------------------------------------------------------*/
 /* geniCodeArray2Ptr - array to pointer                            */
 /*-----------------------------------------------------------------*/
-operand *
+static operand *
 geniCodeArray2Ptr (operand * op)
 {
   sym_link *optype = operandType (op);
@@ -2295,10 +2393,11 @@ geniCodeArray2Ptr (operand * op)
 /*-----------------------------------------------------------------*/
 /* geniCodeArray - array access                                    */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeArray (operand * left, operand * right,int lvl)
+static operand *
+geniCodeArray (operand * left, operand * right, int lvl)
 {
   iCode *ic;
+  operand *size;
   sym_link *ltype = operandType (left);
   bool indexUnsigned;
 
@@ -2309,24 +2408,38 @@ geniCodeArray (operand * left, operand * right,int lvl)
          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,
-                           operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+                           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)
     SPEC_USIGN (getSpec (operandType (right))) = 1;
   /* we can check for limits here */
+  /* already done in SDCCast.c
   if (isOperandLiteral (right) &&
       IS_ARRAY (ltype) &&
       DCL_ELEM (ltype) &&
       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
     {
-      werror (E_ARRAY_BOUND);
-      right = operandFromLit (0);
+      werror (W_IDX_OUT_OF_BOUNDS,
+             (int) operandLitValue (right) / getSize (ltype->next),
+             DCL_ELEM (ltype));
     }
+  */
 
   ic = newiCode ('+', left, right);
 
@@ -2731,7 +2844,6 @@ geniCodeLeftShift (operand * left, operand * right)
 {
   iCode *ic;
 
-  left = usualUnaryConversions (left);
   ic = newiCode (LEFT_OP, left, right);
   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
   ADDTOCHAIN (ic);
@@ -2814,7 +2926,7 @@ geniCodeLogic (operand * left, operand * right, int op)
         }
     }
 
-  ctype = usualBinaryConversions (&left, &right, FALSE, FALSE);
+  ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, ' ');
 
   ic = newiCode (op, left, right);
   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
@@ -3012,7 +3124,7 @@ geniCodeSEParms (ast * parms,int lvl)
 /*-----------------------------------------------------------------*/
 value *
 geniCodeParms (ast * parms, value *argVals, int *stack, 
-              sym_link * fetype, symbol * func,int lvl)
+              sym_link * ftype, int lvl)
 {
   iCode *ic;
   operand *pval;
@@ -3022,14 +3134,14 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
 
   if (argVals==NULL) {
     // first argument
-    argVals=FUNC_ARGS(func->type);
+    argVals = FUNC_ARGS (ftype);
   }
 
   /* if this is a param node then do the left & right */
   if (parms->type == EX_OP && parms->opval.op == PARAM)
     {
-      argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
-      argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
+      argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
+      argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
       return argVals;
     }
 
@@ -3053,18 +3165,18 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
     }
 
   /* if register parm then make it a send */
-  if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
-      IFFUNC_ISBUILTIN(func->type))
+  if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
+      IFFUNC_ISBUILTIN(ftype))
     {
       ic = newiCode (SEND, pval, NULL);
       ic->argreg = SPEC_ARGREG(parms->etype);
-      ic->builtinSEND = FUNC_ISBUILTIN(func->type);
+      ic->builtinSEND = FUNC_ISBUILTIN(ftype);
       ADDTOCHAIN (ic);
     }
   else
     {
       /* now decide whether to push or assign */
-      if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
+      if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
        {
 
          /* assign */
@@ -3098,6 +3210,7 @@ geniCodeCall (operand * left, ast * parms,int lvl)
   iCode *ic;
   operand *result;
   sym_link *type, *etype;
+  sym_link *ftype;
   int stack = 0;
 
   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
@@ -3111,8 +3224,12 @@ geniCodeCall (operand * left, ast * parms,int lvl)
      of overlaying function parameters */
   geniCodeSEParms (parms,lvl);
 
+  ftype = operandType (left);
+  if (IS_CODEPTR (ftype))
+    ftype = ftype->next;
+    
   /* first the parameters */
-  geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
+  geniCodeParms (parms, NULL, &stack, ftype, lvl);
 
   /* now call : if symbol then pcall */
   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
@@ -3121,7 +3238,7 @@ geniCodeCall (operand * left, ast * parms,int lvl)
     ic = newiCode (CALL, left, NULL);
   }
 
-  type = copyLinkChain (operandType (left)->next);
+  type = copyLinkChain (ftype->next);
   etype = getSpec (type);
   SPEC_EXTR (etype) = 0;
   IC_RESULT (ic) = result = newiTempOperand (type, 1);
@@ -3398,7 +3515,7 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* 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);
     }
@@ -3502,7 +3619,7 @@ geniCodeInline (ast * tree)
 /*-----------------------------------------------------------------*/
 /* geniCodeArrayInit - intermediate code for array initializer     */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeArrayInit (ast * tree, operand *array)
 {
   iCode *ic;
@@ -3765,29 +3882,35 @@ ast2iCode (ast * tree,int lvl)
 
     case '/':
       return geniCodeDivision (geniCodeRValue (left, FALSE),
-                              geniCodeRValue (right, FALSE));
+                              geniCodeRValue (right, FALSE),
+                              getResultTypeFromType (tree->ftype));
 
     case '%':
       return geniCodeModulus (geniCodeRValue (left, FALSE),
-                             geniCodeRValue (right, FALSE));
+                             geniCodeRValue (right, FALSE),
+                             getResultTypeFromType (tree->ftype));
     case '*':
       if (right)
        return geniCodeMultiply (geniCodeRValue (left, FALSE),
-                                geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
+                                geniCodeRValue (right, FALSE),
+                                getResultTypeFromType (tree->ftype));
       else
        return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
     case '-':
-      if (right) 
+      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 */
 
@@ -3878,20 +4001,25 @@ ast2iCode (ast * tree,int lvl)
        geniCodeAssign (left,
                geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE),FALSE), 0);
+                                 geniCodeRValue (right, FALSE), FALSE),
+                                 getResultTypeFromType (tree->ftype));
 
     case DIV_ASSIGN:
       return
        geniCodeAssign (left,
                geniCodeDivision (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype)),
+                       0);
     case MOD_ASSIGN:
       return
        geniCodeAssign (left,
                 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype)),
+                       0);
     case ADD_ASSIGN:
       {
        sym_link *rtype = operandType (right);
@@ -3906,7 +4034,10 @@ ast2iCode (ast * tree,int lvl)
        return geniCodeAssign (left,
                     geniCodeAdd (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 right,lvl), 0);
+                                 right,
+                                 getResultTypeFromType (tree->ftype),
+                                 lvl),
+                              0);
       }
     case SUB_ASSIGN:
       {
@@ -3925,7 +4056,9 @@ ast2iCode (ast * tree,int lvl)
          geniCodeAssign (left,
                geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 right), 0);
+                                 right,
+                                 getResultTypeFromType (tree->ftype)),
+                         0);
       }
     case LEFT_ASSIGN:
       return