* Added support for doing shifts by helper functions
[fw/sdcc] / src / SDCCicode.c
index e9f6b3b1401227e4ed564186f2c05802c646694c..4e93c888ce17805e5b38e4ade37243139f6c8165 100644 (file)
@@ -37,7 +37,6 @@ char *filename;
 int lineno;
 int block;
 int scopeLevel;
-int lvaluereq;
 
 symbol *returnLabel;           /* function return label */
 symbol *entryLabel;            /* function entry  label */
@@ -45,13 +44,14 @@ symbol *entryLabel;         /* function entry  label */
 /* forward definition of some functions */
 operand *geniCodeDivision (operand *, operand *);
 operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *);
+operand *geniCodeArray (operand *, operand *,int);
 operand *geniCodeArray2Ptr (operand *);
 operand *geniCodeRValue (operand *, bool);
-operand *geniCodeDerefPtr (operand *);
+operand *geniCodeDerefPtr (operand *,int);
+int isLvaluereq(int lvl);
 
 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
-/* forward definition of print functions */
+/* forward definition of ic print functions */
 PRINTFUNC (picGetValueAtAddr);
 PRINTFUNC (picSetValueAtAddr);
 PRINTFUNC (picAddrOf);
@@ -398,6 +398,10 @@ piCode (void *item, FILE * of)
   return 1;
 }
 
+void PICC(iCode *ic)
+{
+       printiCChain(ic,stdout);
+}
 /*-----------------------------------------------------------------*/
 /* printiCChain - prints intermediate code for humans              */
 /*-----------------------------------------------------------------*/
@@ -535,7 +539,7 @@ newiTempLabel (char *s)
   itmplbl->isitmp = 1;
   itmplbl->islbl = 1;
   itmplbl->key = labelKey++;
-  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
+  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
   return itmplbl;
 }
 
@@ -553,7 +557,7 @@ newiTempPreheaderLabel ()
   itmplbl->isitmp = 1;
   itmplbl->islbl = 1;
   itmplbl->key = labelKey++;
-  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
+  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
   return itmplbl;
 }
 
@@ -579,6 +583,7 @@ copyiCode (iCode * ic)
   nic->filename = ic->filename;
   nic->block = ic->block;
   nic->level = ic->level;
+  nic->parmBytes = ic->parmBytes;
 
   /* deal with the special cases first */
   switch (ic->op)
@@ -834,11 +839,15 @@ operand *
 operandOperation (operand * left, operand * right,
                  int op, sym_link * type)
 {
+  sym_link *let , *ret=NULL;
   operand *retval = (operand *) 0;
-
+  
   assert (isOperandLiteral (left));
-  if (right)
+  let = getSpec(operandType(left));
+  if (right) {
     assert (isOperandLiteral (right));
+    ret = getSpec(operandType(left));
+  }
 
   switch (op)
     {
@@ -870,22 +879,34 @@ operandOperation (operand * left, operand * right,
                                                   operandLitValue (right)));
       break;
     case '%':
-      if ((unsigned long) operandLitValue (right) == 0)
-       {
+      if ((unsigned long) operandLitValue (right) == 0) {
          werror (E_DIVIDE_BY_ZERO);
          retval = right;
-       }
-      else
-       retval = operandFromLit ((unsigned long) operandLitValue (left) %
-                                (unsigned long) operandLitValue (right));
+      }
+      else 
+       retval = operandFromLit ((SPEC_USIGN(let) ? 
+                                 (unsigned long) operandLitValue (left) :
+                                 (long) operandLitValue (left)) %
+                                (SPEC_USIGN(ret) ? 
+                                 (unsigned long) operandLitValue (right) :
+                                 (long) operandLitValue (right)));
+
       break;
     case LEFT_OP:
-      retval = operandFromLit ((unsigned long) operandLitValue (left) <<
-                              (unsigned long) operandLitValue (right));
+      retval = operandFromLit (((SPEC_USIGN(let) ? 
+                                 (unsigned long) operandLitValue (left) :
+                                 (long) operandLitValue (left)) <<
+                                (SPEC_USIGN(ret) ? 
+                                 (unsigned long) operandLitValue (right) :
+                                 (long) operandLitValue (right))));
       break;
     case RIGHT_OP:
-      retval = operandFromLit ((unsigned long) operandLitValue (left) >>
-                              (unsigned long) operandLitValue (right));
+      retval = operandFromLit (((SPEC_USIGN(let) ? 
+                                 (unsigned long) operandLitValue (left) :
+                                 (long) operandLitValue (left)) >>
+                                (SPEC_USIGN(ret) ? 
+                                 (unsigned long) operandLitValue (right) :
+                                 (long) operandLitValue (right))));
       break;
     case EQ_OP:
       retval = operandFromLit (operandLitValue (left) ==
@@ -933,7 +954,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RRC:
       {
-       long i = operandLitValue (left);
+       long i = (long) operandLitValue (left);
 
        retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
                                 (i << 1));
@@ -941,7 +962,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RLC:
       {
-       long i = operandLitValue (left);
+       long i = (long) operandLitValue (left);
 
        retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
                                 (i >> 1));
@@ -1000,7 +1021,7 @@ isOperandEqual (operand * left, operand * right)
       return (floatFromVal (left->operand.valOperand) ==
              floatFromVal (right->operand.valOperand));
     case TYPE:
-      if (checkType (left->operand.typeOperand,
+      if (compareType (left->operand.typeOperand,
                     right->operand.typeOperand) == 1)
        return 1;
     }
@@ -1071,7 +1092,6 @@ newiTempFromOp (operand * op)
   nop->noSpilLoc = op->noSpilLoc;
   nop->usesDefs = op->usesDefs;
   nop->isParm = op->isParm;
-  nop->parmBytes = op->parmBytes;
   return nop;
 }
 
@@ -1095,7 +1115,6 @@ operandFromOperand (operand * op)
   nop->noSpilLoc = op->noSpilLoc;
   nop->usesDefs = op->usesDefs;
   nop->isParm = op->isParm;
-  nop->parmBytes = op->parmBytes;
 
   switch (nop->type)
     {
@@ -1157,14 +1176,13 @@ operandFromSymbol (symbol * sym)
       op->key = sym->key;
       op->isvolatile = isOperandVolatile (op, TRUE);
       op->isGlobal = isOperandGlobal (op);
-      op->parmBytes = sym->argStack;
       return op;
     }
 
   /* under the following conditions create a
      register equivalent for a local symbol */
   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
-      (IN_FARSPACE (SPEC_OCLS (sym->etype)) && (!IS_DS390_PORT)) &&
+      (IN_FARSPACE (SPEC_OCLS (sym->etype)) && (!TARGET_IS_DS390)) &&
       options.stackAuto == 0)
     ok = 0;
 
@@ -1276,7 +1294,7 @@ operandFromLink (sym_link * type)
 /* operandFromLit - makes an operand from a literal value          */
 /*-----------------------------------------------------------------*/
 operand *
-operandFromLit (float i)
+operandFromLit (double i)
 {
   return operandFromValue (valueFromLit (i));
 }
@@ -1285,7 +1303,7 @@ operandFromLit (float i)
 /* operandFromAst - creates an operand from an ast                 */
 /*-----------------------------------------------------------------*/
 operand *
-operandFromAst (ast * tree)
+operandFromAst (ast * tree,int lvl)
 {
 
   if (!tree)
@@ -1295,7 +1313,7 @@ operandFromAst (ast * tree)
   switch (tree->type)
     {
     case EX_OP:
-      return ast2iCode (tree);
+      return ast2iCode (tree,lvl+1);
       break;
 
     case EX_VALUE:
@@ -1343,6 +1361,43 @@ setOperandType (operand * op, sym_link * type)
     }
 
 }
+/*-----------------------------------------------------------------*/
+/* Get size in byte of ptr need to access an array                 */
+/*-----------------------------------------------------------------*/
+int
+getArraySizePtr (operand * op)
+{
+  sym_link *ltype = operandType(op);
+
+  if(IS_PTR(ltype))
+    {
+      int size = getSize(ltype);
+      return(IS_GENPTR(ltype)?(size-1):size);
+    }
+
+  if(IS_ARRAY(ltype))
+    {
+      sym_link *letype = getSpec(ltype);
+      switch (PTR_TYPE (SPEC_OCLS (letype)))
+       {
+       case IPOINTER:
+       case PPOINTER:
+       case POINTER:
+         return (PTRSIZE);
+       case EEPPOINTER:
+       case FPOINTER:
+       case CPOINTER:
+       case FUNCTION:
+         return (FPTRSIZE);
+       case GPOINTER:
+         return (GPTRSIZE-1);
+
+       default:
+         return (FPTRSIZE);
+       }
+    }
+  return (FPTRSIZE);
+}
 
 /*-----------------------------------------------------------------*/
 /* perform "usual unary conversions"                               */
@@ -1352,7 +1407,7 @@ usualUnaryConversions (operand * op)
 {
   if (IS_INTEGRAL (operandType (op)))
     {
-      if (getSize (operandType (op)) < INTSIZE)
+      if (getSize (operandType (op)) < (unsigned int) INTSIZE)
        {
          /* Widen to int. */
          return geniCodeCast (INTTYPE, op, TRUE);
@@ -1367,122 +1422,17 @@ usualUnaryConversions (operand * op)
 sym_link *
 usualBinaryConversions (operand ** op1, operand ** op2)
 {
-  if (!options.ANSIint)
-    {
-      /* "Classic" SDCC behavior. */
-      sym_link *ctype;
-      sym_link *rtype = operandType (*op2);
-      sym_link *ltype = operandType (*op1);
-
-      ctype = computeType (ltype, rtype);
-      *op1 = geniCodeCast (ctype, *op1, TRUE);
-      *op2 = geniCodeCast (ctype, *op2, TRUE);
-
-      return ctype;
-    }
-
-  *op1 = usualUnaryConversions (*op1);
-  *op2 = usualUnaryConversions (*op2);
-
-  /* Try to make the two operands of the same type, following
-   * the "usual binary conversions" promotion rules.
-   *
-   * NB: floating point types are not yet properly handled; we
-   * follow the "classic" behavior.
-   */
-
-  if (IS_FLOAT (operandType (*op1)) || IS_FLOAT (operandType (*op2)))
-    {
-      return newFloatLink ();
-    }
-
-  if (!IS_INTEGRAL (operandType (*op1)) || !IS_INTEGRAL (operandType (*op2)))
-    {
-      /* if either is not an integer type, we're done. */
-      return copyLinkChain (operandType (*op1));       /* Punt! we should never get here. */
-    }
-
-  /* If either is an unsigned long, make sure both are. */
-  if (SPEC_USIGN (operandType (*op1)) && IS_LONG (operandType (*op1)))
-    {
-      if (!SPEC_USIGN (operandType (*op2)) || !IS_LONG (operandType (*op2)))
-       {
-         *op2 = geniCodeCast (ULONGTYPE, *op2, TRUE);
-       }
-      return copyLinkChain (operandType (*op1));
-    }
-
-  if (SPEC_USIGN (operandType (*op2)) && IS_LONG (operandType (*op2)))
-    {
-      if (!SPEC_USIGN (operandType (*op1)) || !IS_LONG (operandType (*op1)))
-       {
-         *op1 = geniCodeCast (ULONGTYPE, *op1, TRUE);
-       }
-      return copyLinkChain (operandType (*op2));
-    }
-
-  /* Next, if one is long and the other is int (signed or un),
-   * cast both to long.
-   *
-   * Note that because in our environment a long can hold all
-   * the values of an unsigned int, the "long/unsigned int" pair
-   * in the ANSI conversion table is unnecessary; this test
-   * handles that case implicitly.
-   */
-  if (IS_LONG (operandType (*op1)))
-    {
-      /* NB: because of the unary conversions, op2 cannot
-       * be smaller than int. Therefore, if it is not
-       * long, it is a regular int.
-       */
-      if (!IS_LONG (operandType (*op2)))
-       {
-         *op2 = geniCodeCast (LONGTYPE, *op2, TRUE);
-       }
-      return copyLinkChain (operandType (*op1));
-    }
-
-  if (IS_LONG (operandType (*op2)))
-    {
-      /* NB: because of the unary conversions, op2 cannot
-       * be smaller than int. Therefore, if it is not
-       * long, it is a regular int.
-       */
-      if (!IS_LONG (operandType (*op1)))
-       {
-         *op1 = geniCodeCast (LONGTYPE, *op1, TRUE);
-       }
-      return copyLinkChain (operandType (*op2));
-    }
-
-  /* All right, neither is long; they must both be integers.
-
-   * Only remaining issue is signed vs. unsigned; if one is unsigned
-   * and the other isn't, convert both to unsigned.
-   */
-  if (SPEC_USIGN (operandType (*op1)))
-    {
-      if (!SPEC_USIGN (operandType (*op2)))
-       {
-         *op2 = geniCodeCast (UINTTYPE, *op2, TRUE);
-       }
-      return copyLinkChain (operandType (*op1));
-    }
-
-  if (SPEC_USIGN (operandType (*op2)))
-    {
-      if (!SPEC_USIGN (operandType (*op1)))
-       {
-         *op1 = geniCodeCast (UINTTYPE, *op1, TRUE);
-       }
-      return copyLinkChain (operandType (*op2));
-    }
-
-  /* Done! */
-  return copyLinkChain (operandType (*op1));
+  sym_link *ctype;
+  sym_link *rtype = operandType (*op2);
+  sym_link *ltype = operandType (*op1);
+  
+  ctype = computeType (ltype, rtype);
+  *op1 = geniCodeCast (ctype, *op1, TRUE);
+  *op2 = geniCodeCast (ctype, *op2, TRUE);
+  
+  return ctype;
 }
 
-
 /*-----------------------------------------------------------------*/
 /* geniCodeValueAtAddress - generate intermeditate code for value  */
 /*                          at address                             */
@@ -1517,7 +1467,7 @@ geniCodeRValue (operand * op, bool force)
 
   if (IS_SPEC (type) &&
       IS_TRUE_SYMOP (op) &&
-      (!IN_FARSPACE (SPEC_OCLS (etype)) || IS_DS390_PORT))
+      (!IN_FARSPACE (SPEC_OCLS (etype)) || TARGET_IS_DS390))
     {
       op = operandFromOperand (op);
       op->isaddr = 0;
@@ -1563,7 +1513,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
     }
 
   /* if the operand is already the desired type then do nothing */
-  if (checkType (type, optype) == 1)
+  if (compareType (type, optype) == 1)
     return op;
 
   /* if this is a literal then just change the type & return */
@@ -1579,7 +1529,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
       !IS_GENPTR (type))
     {
       werror (E_INCOMPAT_CAST);
-      werror (E_CONTINUE, "from type '");
+      fprintf (stderr, "from type '");
       printTypeChain (optype, stderr);
       fprintf (stderr, "' to type '");
       printTypeChain (type, stderr);
@@ -1647,11 +1597,10 @@ geniCodeGoto (symbol * label)
 /* geniCodeMultiply - gen intermediate code for multiplication     */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeMultiply (operand * left, operand * right, bool ptrSizeCalculation)
+geniCodeMultiply (operand * left, operand * right,int resultIsInt)
 {
   iCode *ic;
   int p2 = 0;
-  int saveOption;
   sym_link *resType;
   LRTYPE;
 
@@ -1660,50 +1609,38 @@ geniCodeMultiply (operand * left, operand * right, bool ptrSizeCalculation)
     return operandFromValue (valMult (left->operand.valOperand,
                                      right->operand.valOperand));
 
+  if (IS_LITERAL(retype)) {
+    p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
+  }
 
-  //Force 1 byte * 1 byte = 2 bytes result if we are computing ptr size
-  if ((ptrSizeCalculation) && (1 == getSize (rtype)) &&
-      (1 == getSize (ltype)))
+  resType = usualBinaryConversions (&left, &right);
+#if 1
+  rtype = operandType (right);
+  retype = getSpec (rtype);
+  ltype = operandType (left);
+  letype = getSpec (ltype);
+#endif
+  if (resultIsInt)
     {
-      saveOption = options.ANSIint;
-      options.ANSIint = 0;
-      resType = usualBinaryConversions (&left, &right);
-      ltype = operandType (left);
-      rtype = operandType (right);
-      SPEC_SHORT (getSpec (resType)) = 0;
-      options.ANSIint = saveOption;
-    }
-  else {
-    resType = usualBinaryConversions (&left, &right);
-    if (IS_DS390_PORT) {
-      /* jwk char*char=int
-        Now be can use the 16bit result of "mul a,b" instead of explicit
-        casts and support function calls as with --ansiint
-      */
-      if ((IS_CHAR(letype) || IS_SHORT(letype)) && 
-          (IS_CHAR(retype) || IS_SHORT(retype))) {
-       SPEC_NOUN(getSpec(resType))=V_INT;
-       SPEC_SHORT(getSpec(resType))=0;
-      }
+      SPEC_NOUN(getSpec(resType))=V_INT;
     }
-  }
 
   /* if the right is a literal & power of 2 */
   /* then make it a left shift              */
-  /*If we are computing  ptr size then normal multiplication */
-  /*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 as 1 byte muldiv */
-  if (IS_LITERAL (retype) && !IS_FLOAT (letype) &&
-      !((ptrSizeCalculation) && (getSize (resType) != getSize (ltype)) && (1 == port->muldiv.native_below)) &&
-   (p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand))))
-    {
-      if ((ptrSizeCalculation) && (getSize (resType) != getSize (ltype)))
+  /* 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 ((resultIsInt) && (getSize (resType) != getSize (ltype)))
        {
          /* LEFT_OP need same size for left and result, */
          left = geniCodeCast (resType, left, TRUE);
          ltype = operandType (left);
        }
-      ic = newiCode (LEFT_OP, left, operandFromLit (p2));      /* left shift */
+      ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
     }
   else
     {
@@ -1740,8 +1677,9 @@ geniCodeDivision (operand * left, operand * right)
   if (IS_LITERAL (retype) &&
       !IS_FLOAT (letype) &&
       (p2 = powof2 ((unsigned long)
-                   floatFromVal (right->operand.valOperand))))
-    ic = newiCode (RIGHT_OP, left, operandFromLit (p2));       /* right shift */
+                   floatFromVal (right->operand.valOperand)))) {
+    ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
+  }
   else
     {
       ic = newiCode ('/', left, right);                /* normal division */
@@ -1838,7 +1776,7 @@ geniCodeSubtract (operand * left, operand * right)
     {
       isarray = left->isaddr;
       right = geniCodeMultiply (right,
-                             operandFromLit (getSize (ltype->next)), TRUE);
+                               operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
     }
   else
@@ -1863,7 +1801,7 @@ geniCodeSubtract (operand * left, operand * right)
 /* geniCodeAdd - generates iCode for addition                      */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeAdd (operand * left, operand * right)
+geniCodeAdd (operand * left, operand * right,int lvl)
 {
   iCode *ic;
   sym_link *resType;
@@ -1873,7 +1811,7 @@ geniCodeAdd (operand * left, operand * right)
 
   /* if left is an array then array access */
   if (IS_ARRAY (ltype))
-    return geniCodeArray (left, right);
+    return geniCodeArray (left, right,lvl);
 
   /* if the right side is LITERAL zero */
   /* return the left side              */
@@ -1887,13 +1825,12 @@ geniCodeAdd (operand * left, operand * right)
   /* if left is an array or pointer then size */
   if (IS_PTR (ltype))
     {
-
       isarray = left->isaddr;
-      size =
-       operandFromLit (getSize (ltype->next));
-
-      right = geniCodeMultiply (right, size, (getSize (ltype) != 1));
-
+      // there is no need to multiply with 1
+      if (getSize(ltype->next)!=1) {
+       size  = operandFromLit (getSize (ltype->next));
+       right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
+      }
       resType = copyLinkChain (ltype);
     }
   else
@@ -1986,7 +1923,7 @@ geniCodeArray2Ptr (operand * op)
 /* geniCodeArray - array access                                    */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeArray (operand * left, operand * right)
+geniCodeArray (operand * left, operand * right,int lvl)
 {
   iCode *ic;
   sym_link *ltype = operandType (left);
@@ -1997,12 +1934,11 @@ geniCodeArray (operand * left, operand * right)
        {
          left = geniCodeRValue (left, FALSE);
        }
-      return geniCodeDerefPtr (geniCodeAdd (left, right));
+      return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
     }
 
-  /* array access */
   right = geniCodeMultiply (right,
-                           operandFromLit (getSize (ltype->next)), TRUE);
+                           operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
 
   /* we can check for limits here */
   if (isOperandLiteral (right) &&
@@ -2336,7 +2272,7 @@ setOClass (sym_link * ptr, sym_link * spec)
 /* geniCodeDerefPtr - dereference pointer with '*'                 */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeDerefPtr (operand * op)
+geniCodeDerefPtr (operand * op,int lvl)
 {
   sym_link *rtype, *retype;
   sym_link *optype = operandType (op);
@@ -2354,7 +2290,7 @@ geniCodeDerefPtr (operand * op)
     }
 
   /* now get rid of the pointer part */
-  if (lvaluereq && IS_ITEMP (op))
+  if (isLvaluereq(lvl) && IS_ITEMP (op))
     {
       retype = getSpec (rtype = copyLinkChain (optype));
     }
@@ -2380,7 +2316,7 @@ geniCodeDerefPtr (operand * op)
                IS_CHAR (rtype) ||
                IS_FLOAT (rtype));
 
-  if (!lvaluereq)
+  if (!isLvaluereq(lvl))
     op = geniCodeRValue (op, TRUE);
 
   setOperandType (op, rtype);
@@ -2414,16 +2350,6 @@ geniCodeLeftShift (operand * left, operand * right)
 {
   iCode *ic;
 
-
-  /* Note that we don't use the usual binary conversions for the
-   * shift operations, in accordance with our ANSI friends.
-   */
-  if (options.ANSIint)
-    {
-      right = usualUnaryConversions (right);
-      left = usualUnaryConversions (left);
-    }
-
   ic = newiCode (LEFT_OP, left, right);
   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
   ADDTOCHAIN (ic);
@@ -2438,16 +2364,6 @@ geniCodeRightShift (operand * left, operand * right)
 {
   iCode *ic;
 
-
-  /* Note that we don't use the usual binary conversions for the
-   * shift operations, in accordance with our ANSI friends.
-   */
-  if (options.ANSIint)
-    {
-      right = usualUnaryConversions (right);
-      left = usualUnaryConversions (left);
-    }
-
   ic = newiCode (RIGHT_OP, left, right);
   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
   ADDTOCHAIN (ic);
@@ -2476,9 +2392,9 @@ geniCodeLogic (operand * left, operand * right, int op)
   if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
     {
       int nbits = bitsForType (ltype);
-      long v = operandLitValue (right);
+      long v = (long) operandLitValue (right);
 
-      if (v > ((LONG_LONG) 1 << nbits) && v > 0)
+      if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
        werror (W_CONST_RANGE, " compare operation ");
     }
 
@@ -2487,10 +2403,10 @@ geniCodeLogic (operand * left, operand * right, int op)
   ic = newiCode (op, left, right);
   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
 
-  /* if comparing anything greater than one byte
+  /* if comparing float
      and not a '==' || '!=' || '&&' || '||' (these
      will be inlined */
-  if (getSize (ctype) > 1 &&
+  if (IS_FLOAT(ctype) &&
       op != EQ_OP &&
       op != NE_OP &&
       op != AND_OP &&
@@ -2518,19 +2434,19 @@ geniCodeUnary (operand * op, int oper)
 /* geniCodeConditional - geniCode for '?' ':' operation            */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeConditional (ast * tree)
+geniCodeConditional (ast * tree,int lvl)
 {
   iCode *ic;
   symbol *falseLabel = newiTempLabel (NULL);
   symbol *exitLabel = newiTempLabel (NULL);
-  operand *cond = ast2iCode (tree->left);
+  operand *cond = ast2iCode (tree->left,lvl+1);
   operand *true, *false, *result;
 
   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
                          NULL, falseLabel);
   ADDTOCHAIN (ic);
 
-  true = ast2iCode (tree->right->left);
+  true = ast2iCode (tree->right->left,lvl+1);
 
   /* move the value to a new Operand */
   result = newiTempOperand (operandType (true), 0);
@@ -2542,7 +2458,7 @@ geniCodeConditional (ast * tree)
   /* now for the right side */
   geniCodeLabel (falseLabel);
 
-  false = ast2iCode (tree->right->right);
+  false = ast2iCode (tree->right->right,lvl+1);
   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
 
   /* create the exit label */
@@ -2572,9 +2488,9 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
     {
       int nbits = bitsForType (ltype);
-      long v = operandLitValue (right);
+      long v = (long) operandLitValue (right);
 
-      if (v > ((LONG_LONG) 1 << nbits) && v > 0)
+      if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
        werror (W_CONST_RANGE, " = operation");
     }
 
@@ -2585,12 +2501,12 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
 
   /* first check the type for pointer assignement */
   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
-      checkType (ltype, rtype) < 0)
+      compareType (ltype, rtype) < 0)
     {
-      if (checkType (ltype->next, rtype) < 0)
+      if (compareType (ltype->next, rtype) < 0)
        right = geniCodeCast (ltype->next, right, TRUE);
     }
-  else if (checkType (ltype, rtype) < 0)
+  else if (compareType (ltype, rtype) < 0)
     right = geniCodeCast (ltype, right, TRUE);
 
   /* if left is a true symbol & ! volatile
@@ -2629,15 +2545,15 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
 /* geniCodeSEParms - generate code for side effecting fcalls       */
 /*-----------------------------------------------------------------*/
 static void 
-geniCodeSEParms (ast * parms)
+geniCodeSEParms (ast * parms,int lvl)
 {
   if (!parms)
     return;
 
   if (parms->type == EX_OP && parms->opval.op == PARAM)
     {
-      geniCodeSEParms (parms->left);
-      geniCodeSEParms (parms->right);
+      geniCodeSEParms (parms->left,lvl);
+      geniCodeSEParms (parms->right,lvl);
       return;
     }
 
@@ -2652,7 +2568,7 @@ geniCodeSEParms (ast * parms)
     parms->right->left->lvalue = 1;
 
   parms->opval.oprnd =
-    geniCodeRValue (ast2iCode (parms), FALSE);
+    geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
 
   parms->type = EX_OPERAND;
 }
@@ -2661,7 +2577,7 @@ geniCodeSEParms (ast * parms)
 /* geniCodeParms - generates parameters                            */
 /*-----------------------------------------------------------------*/
 static void 
-geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
+geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
 {
   iCode *ic;
   operand *pval;
@@ -2672,8 +2588,8 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
   /* if this is a param node then do the left & right */
   if (parms->type == EX_OP && parms->opval.op == PARAM)
     {
-      geniCodeParms (parms->left, stack, fetype, func);
-      geniCodeParms (parms->right, stack, fetype, func);
+      geniCodeParms (parms->left, stack, fetype, func,lvl);
+      geniCodeParms (parms->right, stack, fetype, func,lvl);
       return;
     }
 
@@ -2693,7 +2609,7 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
          IS_ADDRESS_OF_OP (parms->right))
        parms->right->left->lvalue = 1;
 
-      pval = geniCodeRValue (ast2iCode (parms), FALSE);
+      pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
     }
 
   /* if register parm then make it a send */
@@ -2731,7 +2647,7 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
 /* geniCodeCall - generates temp code for calling                  */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeCall (operand * left, ast * parms)
+geniCodeCall (operand * left, ast * parms,int lvl)
 {
   iCode *ic;
   operand *result;
@@ -2741,13 +2657,13 @@ geniCodeCall (operand * left, ast * parms)
   /* take care of parameters with side-effecting
      function calls in them, this is required to take care
      of overlaying function parameters */
-  geniCodeSEParms (parms);
+  geniCodeSEParms (parms,lvl);
 
   /* first the parameters */
-  geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left));
+  geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
 
   /* now call : if symbol then pcall */
-  if (IS_ITEMP (left))
+  if (IS_OP_POINTER (left) || IS_ITEMP(left))
     ic = newiCode (PCALL, left, NULL);
   else
     ic = newiCode (CALL, left, NULL);
@@ -2761,7 +2677,7 @@ geniCodeCall (operand * left, ast * parms)
   ADDTOCHAIN (ic);
 
   /* stack adjustment after call */
-  left->parmBytes = stack;
+  ic->parmBytes = stack;
 
   return result;
 }
@@ -2790,7 +2706,7 @@ geniCodeReceive (value * args)
 
              if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
                  options.stackAuto == 0 &&
-                 !IS_DS390_PORT)
+                 !TARGET_IS_DS390)
                {
                }
              else
@@ -2819,7 +2735,7 @@ geniCodeReceive (value * args)
 /* geniCodeFunctionBody - create the function body                 */
 /*-----------------------------------------------------------------*/
 void 
-geniCodeFunctionBody (ast * tree)
+geniCodeFunctionBody (ast * tree,int lvl)
 {
   iCode *ic;
   operand *func;
@@ -2832,7 +2748,7 @@ geniCodeFunctionBody (ast * tree)
   iTempLblNum = 0;
   operandKey = 0;
   iCodeKey = 0;
-  func = ast2iCode (tree->left);
+  func = ast2iCode (tree->left,lvl+1);
   fetype = getSpec (operandType (func));
 
   savelineno = lineno;
@@ -2855,7 +2771,7 @@ geniCodeFunctionBody (ast * tree)
   geniCodeReceive (tree->values.args);
 
   /* generate code for the body */
-  ast2iCode (tree->right);
+  ast2iCode (tree->right,lvl+1);
 
   /* create a label for return */
   geniCodeLabel (returnLabel);
@@ -2886,10 +2802,10 @@ geniCodeReturn (operand * op)
 /* geniCodeIfx - generates code for extended if statement          */
 /*-----------------------------------------------------------------*/
 void 
-geniCodeIfx (ast * tree)
+geniCodeIfx (ast * tree,int lvl)
 {
   iCode *ic;
-  operand *condition = ast2iCode (tree->left);
+  operand *condition = ast2iCode (tree->left,lvl+1);
   sym_link *cetype;
 
   /* if condition is null then exit */
@@ -2938,7 +2854,7 @@ geniCodeIfx (ast * tree)
     }
 
 exit:
-  ast2iCode (tree->right);
+  ast2iCode (tree->right,lvl+1);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3036,10 +2952,10 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
 /* geniCodeSwitch - changes a switch to a if statement             */
 /*-----------------------------------------------------------------*/
 void 
-geniCodeSwitch (ast * tree)
+geniCodeSwitch (ast * tree,int lvl)
 {
   iCode *ic;
-  operand *cond = geniCodeRValue (ast2iCode (tree->left), FALSE);
+  operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
   value *caseVals = tree->values.switchVals.swVals;
   symbol *trueLabel, *falseLabel;
 
@@ -3077,7 +2993,7 @@ geniCodeSwitch (ast * tree)
   geniCodeGoto (falseLabel);
 
 jumpTable:
-  ast2iCode (tree->right);
+  ast2iCode (tree->right,lvl+1);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3093,18 +3009,78 @@ geniCodeInline (ast * tree)
   ADDTOCHAIN (ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
+/* particular case. Ie : assigning or dereferencing array or ptr   */
+/*-----------------------------------------------------------------*/
+set * lvaluereqSet = NULL;
+typedef struct lvalItem
+  {
+    int req;
+    int lvl;
+  }
+lvalItem;
+
+/*-----------------------------------------------------------------*/
+/* addLvaluereq - add a flag for lvalreq for current ast level     */
+/*-----------------------------------------------------------------*/
+void addLvaluereq(int lvl)
+{
+  lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
+  lpItem->req=1;
+  lpItem->lvl=lvl;
+  addSetHead(&lvaluereqSet,lpItem);
+
+}
+/*-----------------------------------------------------------------*/
+/* delLvaluereq - del a flag for lvalreq for current ast level     */
+/*-----------------------------------------------------------------*/
+void delLvaluereq()
+{
+  lvalItem * lpItem;
+  lpItem = getSet(&lvaluereqSet);
+  if(lpItem) free(lpItem);
+}
+/*-----------------------------------------------------------------*/
+/* clearLvaluereq - clear lvalreq flag                            */
+/*-----------------------------------------------------------------*/
+void clearLvaluereq()
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) lpItem->req = 0;
+}
+/*-----------------------------------------------------------------*/
+/* getLvaluereq - get the last lvalreq level                      */
+/*-----------------------------------------------------------------*/
+int getLvaluereqLvl()
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) return lpItem->lvl;
+  return 0;
+}
+/*-----------------------------------------------------------------*/
+/* isLvaluereq - is lvalreq valid for this level ?                */
+/*-----------------------------------------------------------------*/
+int isLvaluereq(int lvl)
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
+  return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* ast2iCode - creates an icodeList from an ast                    */
 /*-----------------------------------------------------------------*/
 operand *
-ast2iCode (ast * tree)
+ast2iCode (ast * tree,int lvl)
 {
   operand *left = NULL;
   operand *right = NULL;
-
   if (!tree)
     return NULL;
-
   /* set the global variables for filename & line number */
   if (tree->filename)
     filename = tree->filename;
@@ -3123,11 +3099,11 @@ ast2iCode (ast * tree)
 
   /* if we find a nullop */
   if (tree->type == EX_OP &&
-      (tree->opval.op == NULLOP ||
-       tree->opval.op == BLOCK))
+     (tree->opval.op == NULLOP ||
+     tree->opval.op == BLOCK))
     {
-      ast2iCode (tree->left);
-      ast2iCode (tree->right);
+      ast2iCode (tree->left,lvl+1);
+      ast2iCode (tree->right,lvl+1);
       return NULL;
     }
 
@@ -3143,44 +3119,37 @@ ast2iCode (ast * tree)
       tree->opval.op != INLINEASM)
     {
 
-      if (IS_ASSIGN_OP (tree->opval.op) ||
-         IS_DEREF_OP (tree) ||
-         (tree->opval.op == '&' && !tree->right) ||
-         tree->opval.op == PTR_OP)
-       {
-         lvaluereq++;
-         if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
-             (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
-           {
-             int olvr = lvaluereq;
-             lvaluereq = 0;
-             left = operandFromAst (tree->left);
-             lvaluereq = olvr - 1;
-           }
-         else
-           {
-             left = operandFromAst (tree->left);
-             lvaluereq--;
-           }
-         if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
-           left = geniCodeRValue (left, TRUE);
-       }
-      else
-       {
-         left = operandFromAst (tree->left);
-       }
-      if (tree->opval.op == INC_OP ||
-         tree->opval.op == DEC_OP)
-       {
-         lvaluereq++;
-         right = operandFromAst (tree->right);
-         lvaluereq--;
-       }
-      else
-       {
-         right = operandFromAst (tree->right);
-       }
-    }
+        if (IS_ASSIGN_OP (tree->opval.op) ||
+           IS_DEREF_OP (tree) ||
+           (tree->opval.op == '&' && !tree->right) ||
+           tree->opval.op == PTR_OP)
+          {
+            addLvaluereq(lvl);
+            if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
+               (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
+              clearLvaluereq();
+
+            left = operandFromAst (tree->left,lvl);
+            delLvaluereq();
+            if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
+             left = geniCodeRValue (left, TRUE);
+          }
+        else
+          {
+           left = operandFromAst (tree->left,lvl);
+          }
+        if (tree->opval.op == INC_OP ||
+           tree->opval.op == DEC_OP)
+          {
+           addLvaluereq(lvl);
+           right = operandFromAst (tree->right,lvl);
+           delLvaluereq();
+          }
+        else
+          {
+           right = operandFromAst (tree->right,lvl);
+          }
+      }
 
   /* now depending on the type of operand */
   /* this will be a biggy                 */
@@ -3194,7 +3163,7 @@ ast2iCode (ast * tree)
        right = geniCodeRValue (right, TRUE);
       }
 
-      return geniCodeArray (left, right);
+      return geniCodeArray (left, right,lvl);
 
     case '.':                  /* structure dereference */
       if (IS_PTR (operandType (left)))
@@ -3254,9 +3223,9 @@ ast2iCode (ast * tree)
     case '*':
       if (right)
        return geniCodeMultiply (geniCodeRValue (left, FALSE),
-                                geniCodeRValue (right, FALSE), FALSE);
+                                geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
       else
-       return geniCodeDerefPtr (geniCodeRValue (left, FALSE));
+       return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
     case '-':
       if (right)
@@ -3268,7 +3237,7 @@ ast2iCode (ast * tree)
     case '+':
       if (right)
        return geniCodeAdd (geniCodeRValue (left, FALSE),
-                           geniCodeRValue (right, FALSE));
+                           geniCodeRValue (right, FALSE),lvl);
       else
        return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
 
@@ -3307,7 +3276,7 @@ ast2iCode (ast * tree)
                            geniCodeRValue (right, FALSE),
                            tree->opval.op);
     case '?':
-      return geniCodeConditional (tree);
+      return geniCodeConditional (tree,lvl);
 
     case SIZEOF:
       return operandFromLit (getSize (tree->right->ftype));
@@ -3317,7 +3286,7 @@ ast2iCode (ast * tree)
        sym_link *rtype = operandType (right);
        sym_link *ltype = operandType (left);
        if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && checkType (rtype->next, ltype) == 1)
+           && right->isaddr && compareType (rtype->next, ltype) == 1)
          right = geniCodeRValue (right, TRUE);
        else
          right = geniCodeRValue (right, FALSE);
@@ -3330,7 +3299,7 @@ ast2iCode (ast * tree)
        geniCodeAssign (left,
                geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE), FALSE), 0);
+                                 geniCodeRValue (right, FALSE),FALSE), 0);
 
     case DIV_ASSIGN:
       return
@@ -3349,7 +3318,7 @@ ast2iCode (ast * tree)
        sym_link *rtype = operandType (right);
        sym_link *ltype = operandType (left);
        if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && checkType (rtype->next, ltype) == 1)
+           && right->isaddr && compareType (rtype->next, ltype) == 1)
          right = geniCodeRValue (right, TRUE);
        else
          right = geniCodeRValue (right, FALSE);
@@ -3358,14 +3327,14 @@ ast2iCode (ast * tree)
        return geniCodeAssign (left,
                     geniCodeAdd (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 right), 0);
+                                 right,lvl), 0);
       }
     case SUB_ASSIGN:
       {
        sym_link *rtype = operandType (right);
        sym_link *ltype = operandType (left);
        if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && checkType (rtype->next, ltype) == 1)
+           && right->isaddr && compareType (rtype->next, ltype) == 1)
          {
            right = geniCodeRValue (right, TRUE);
          }
@@ -3419,18 +3388,18 @@ ast2iCode (ast * tree)
       return geniCodeRValue (right, FALSE);
 
     case CALL:
-      return geniCodeCall (ast2iCode (tree->left),
-                          tree->right);
+      return geniCodeCall (ast2iCode (tree->left,lvl+1),
+                          tree->right,lvl);
     case LABEL:
-      geniCodeLabel (ast2iCode (tree->left)->operand.symOperand);
-      return ast2iCode (tree->right);
+      geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+      return ast2iCode (tree->right,lvl+1);
 
     case GOTO:
-      geniCodeGoto (ast2iCode (tree->left)->operand.symOperand);
-      return ast2iCode (tree->right);
+      geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+      return ast2iCode (tree->right,lvl+1);
 
     case FUNCTION:
-      geniCodeFunctionBody (tree);
+      geniCodeFunctionBody (tree,lvl);
       return NULL;
 
     case RETURN:
@@ -3438,11 +3407,11 @@ ast2iCode (ast * tree)
       return NULL;
 
     case IFX:
-      geniCodeIfx (tree);
+      geniCodeIfx (tree,lvl);
       return NULL;
 
     case SWITCH:
-      geniCodeSwitch (tree);
+      geniCodeSwitch (tree,lvl);
       return NULL;
 
     case INLINEASM:
@@ -3482,6 +3451,6 @@ iCodeFromAst (ast * tree)
 {
   returnLabel = newiTempLabel ("_return");
   entryLabel = newiTempLabel ("_entry");
-  ast2iCode (tree);
+  ast2iCode (tree,0);
   return reverseiCChain ();
 }