* src/SDCCicode.c (isOperandEqual): fixed missing ;
[fw/sdcc] / src / SDCCicode.c
index 3364eecf87dede007a92f8104ad4bd76bb81f318..5c38ec8f80937d5f2167fe196dbcd98b057f5332 100644 (file)
@@ -45,7 +45,7 @@ symbol *entryLabel;           /* function entry  label */
 
 /*-----------------------------------------------------------------*/
 /* forward definition of some functions */
-operand *geniCodeAssign (operand *, operand *, int);
+operand *geniCodeAssign (operand *, operand *, int, int);
 static operand *geniCodeArray (operand *, operand *,int);
 static operand *geniCodeArray2Ptr (operand *);
 operand *geniCodeRValue (operand *, bool);
@@ -120,7 +120,8 @@ iCodeTable codeTable[] =
   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
   {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
   {CRITICAL, "critical_start", picCritical, NULL},
-  {ENDCRITICAL, "critical_end", picEndCritical, NULL}
+  {ENDCRITICAL, "critical_end", picEndCritical, NULL},
+  {SWAP, "swap", picGenericOne, NULL}
 };
 
 /*-----------------------------------------------------------------*/
@@ -189,7 +190,7 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg,
 
 #if 0 // temporary disabled, leaving the warning as a reminder
   if (warnings) {
-    SNPRINTF (message, sizeof(message), "for %s %s in %s", 
+    SNPRINTF (message, sizeof(message), "for %s %s in %s",
             IS_UNSIGNED(ltype) ? "unsigned" : "signed",
             nounName(ltype), msg);
     werror (W_CONST_RANGE, message);
@@ -203,7 +204,7 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg,
 /*-----------------------------------------------------------------*/
 /* operandName - returns the name of the operand                   */
 /*-----------------------------------------------------------------*/
-int 
+int
 printOperand (operand * op, FILE * file)
 {
   sym_link *opetype;
@@ -232,13 +233,14 @@ printOperand (operand * op, FILE * file)
 
     case SYMBOL:
 #define REGA 1
-#ifdef REGA
-      fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d ru%d dp%d}",                /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}"  , */
+//#if REGA     /* { */
+    if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
+      fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d a2p%d re%d rm%d nos%d ru%d dp%d}",          /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}"  , */
               (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
               op->key,
               OP_LIVEFROM (op), OP_LIVETO (op),
               OP_SYMBOL (op)->stack,
-              op->isaddr, OP_SYMBOL (op)->isreqv, 
+              op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv,
               OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
               OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
        );
@@ -275,21 +277,53 @@ printOperand (operand * op, FILE * file)
              fprintf (file, "]");
            }
        }
-#else
-      fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
-                           OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
+//#else                /* } else { */
+    } else {
+      /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
+      fprintf (file, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
+
+      if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
+        {
+          fprintf (file, "[lr%d:%d so:%d]",
+              OP_LIVEFROM (op), OP_LIVETO (op),
+              OP_SYMBOL (op)->stack);
+        }
+
+      if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
+        {
+          fprintf (file, "{");
+          printTypeChain (operandType (op), file);
+          if (SPIL_LOC (op) && IS_ITEMP (op))
+              fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
+          fprintf (file, "}");
+        }
+
       /* if assigned to registers */
-      if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
+      if (OP_SYMBOL (op)->nRegs)
        {
-         int i;
-         fprintf (file, "[");
-         for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
-           fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
-                                  OP_SYMBOL (op)->regs[i]->name :
-                                  "err"));
-         fprintf (file, "]");
+         if (OP_SYMBOL (op)->isspilt)
+           {
+             if (!OP_SYMBOL (op)->remat)
+               if (OP_SYMBOL (op)->usl.spillLoc)
+                 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
+                                      OP_SYMBOL (op)->usl.spillLoc->rname :
+                                      OP_SYMBOL (op)->usl.spillLoc->name));
+               else
+                 fprintf (file, "[err]");
+             else
+               fprintf (file, "[remat]");
+           }
+         else
+           {
+             int i;
+             fprintf (file, "[");
+             for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
+               fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
+             fprintf (file, "]");
+           }
        }
-#endif
+//#endif               /* } */
+    }
       break;
 
     case TYPE:
@@ -398,6 +432,9 @@ PRINTFUNC (picGenericOne)
   if (ic->op == SEND || ic->op == RECEIVE) {
       fprintf(of,"{argreg = %d}",ic->argreg);
   }
+  if (ic->op == IPUSH) {
+      fprintf(of,"{parmPush = %d}",ic->parmPush);
+  }
   fprintf (of, "\n");
 }
 
@@ -513,7 +550,7 @@ piCode (void *item, FILE * of)
     of = stdout;
 
   icTab = getTableEntry (ic->op);
-  fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
+  fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
           ic->filename, ic->lineno,
           ic->seq, ic->key, ic->depth, ic->supportRtn);
   icTab->iCodePrint (of, ic, icTab->printName);
@@ -640,7 +677,7 @@ newiTemp (char *s)
   {
       SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
   }
-    
+
   itmp = newSymbol (buffer, 1);
   strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
   itmp->isitmp = 1;
@@ -656,13 +693,13 @@ newiTempLabel (char *s)
 {
   symbol *itmplbl;
 
-  /* check if this alredy exists */
+  /* check if this already exists */
   if (s && (itmplbl = findSym (LabelTab, NULL, s)))
     return itmplbl;
 
   if (s)
     {
-       itmplbl = newSymbol (s, 1);
+      itmplbl = newSymbol (s, 1);
     }
   else
     {
@@ -699,7 +736,7 @@ newiTempPreheaderLabel ()
 /*-----------------------------------------------------------------*/
 /* initiCode - initialises some iCode related stuff                */
 /*-----------------------------------------------------------------*/
-void 
+void
 initiCode ()
 {
 
@@ -834,13 +871,13 @@ operandType (operand * op)
 /*-----------------------------------------------------------------*/
 /* isParamterToCall - will return 1 if op is a parameter to args   */
 /*-----------------------------------------------------------------*/
-int 
+int
 isParameterToCall (value * args, operand * op)
 {
   value *tval = args;
 
   wassert (IS_SYMOP(op));
-    
+
   while (tval)
     {
       if (tval->sym &&
@@ -854,7 +891,7 @@ isParameterToCall (value * args, operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandGlobal   - return 1 if operand is a global variable    */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandGlobal (operand * op)
 {
   if (!op)
@@ -876,7 +913,7 @@ isOperandGlobal (operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandVolatile - return 1 if the operand is volatile         */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandVolatile (operand * op, bool chkTemp)
 {
   sym_link *optype;
@@ -886,19 +923,19 @@ isOperandVolatile (operand * op, bool chkTemp)
     return 0;
 
   opetype = getSpec (optype = operandType (op));
-    
-  if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))   
-    return 1;   
-    
-  if (IS_VOLATILE (opetype))   
-    return 1;   
-  return 0; 
+
+  if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
+    return 1;
+
+  if (IS_VOLATILE (opetype))
+    return 1;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* isOperandLiteral - returns 1 if an operand contains a literal   */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandLiteral (operand * op)
 {
   sym_link *opetype;
@@ -917,7 +954,7 @@ isOperandLiteral (operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandInFarSpace - will return true if operand is in farSpace */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isOperandInFarSpace (operand * op)
 {
   sym_link *etype;
@@ -945,7 +982,7 @@ isOperandInFarSpace (operand * op)
 /*------------------------------------------------------------------*/
 /* isOperandInDirSpace - will return true if operand is in dirSpace */
 /*------------------------------------------------------------------*/
-bool 
+bool
 isOperandInDirSpace (operand * op)
 {
   sym_link *etype;
@@ -973,7 +1010,7 @@ isOperandInDirSpace (operand * op)
 /*--------------------------------------------------------------------*/
 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
 /*--------------------------------------------------------------------*/
-bool 
+bool
 isOperandInCodeSpace (operand * op)
 {
   sym_link *etype;
@@ -1003,7 +1040,7 @@ isOperandInCodeSpace (operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandOnStack - will return true if operand is on stack      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isOperandOnStack (operand * op)
 {
   sym_link *etype;
@@ -1027,7 +1064,7 @@ isOperandOnStack (operand * op)
 /* isOclsExpensive - will return true if accesses to an output     */
 /*                   storage class are expensive                   */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isOclsExpensive (struct memmap *oclass)
 {
   if (port->oclsExpense)
@@ -1038,6 +1075,40 @@ isOclsExpensive (struct memmap *oclass)
   return IN_FARSPACE (oclass);
 }
 
+/*-----------------------------------------------------------------*/
+/* isiCodeInFunctionCall - return TRUE if an iCode is between a    */
+/*   CALL/PCALL and the first IPUSH/SEND associated with the call  */
+/*-----------------------------------------------------------------*/
+int
+isiCodeInFunctionCall (iCode * ic)
+{
+  iCode * lic = ic;
+
+  /* Find the next CALL/PCALL */
+  while (lic)
+    {
+      if (lic->op == CALL || lic->op == PCALL)
+        break;
+      lic = lic->next;
+    }
+
+  if (!lic)
+    return FALSE;
+
+  /* A function call was found. Scan backwards and see if an */
+  /* IPUSH or SEND is encountered */
+  while (ic)
+    {
+      if (lic != ic && (ic->op == CALL || ic->op == PCALL))
+        return FALSE;
+      if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush))
+        return TRUE;
+      ic = ic->prev;
+    }
+
+  return FALSE;
+}
+
 /*-----------------------------------------------------------------*/
 /* operandLitValue - literal value of an operand                   */
 /*-----------------------------------------------------------------*/
@@ -1311,7 +1382,9 @@ operandOperation (operand * left, operand * right,
       break;
 
     case '~':
-      retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 ~((TYPE_UDWORD)
+                                                   operandLitValue (left))));
       break;
 
     case '!':
@@ -1355,8 +1428,10 @@ isOperandEqual (operand * left, operand * right)
       return isSymbolEqual (left->operand.symOperand,
                            right->operand.symOperand);
     case VALUE:
-      return (floatFromVal (left->operand.valOperand) ==
-             floatFromVal (right->operand.valOperand));
+      return (compareType (left->operand.valOperand->type,
+                           right->operand.valOperand->type) &&
+              (floatFromVal (left->operand.valOperand) ==
+               floatFromVal (right->operand.valOperand)));
     case TYPE:
       if (compareType (left->operand.typeOperand,
                     right->operand.typeOperand) == 1)
@@ -1369,7 +1444,7 @@ isOperandEqual (operand * left, operand * right)
 /*-------------------------------------------------------------------*/
 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
 /*-------------------------------------------------------------------*/
-int 
+int
 isiCodeEqual (iCode * left, iCode * right)
 {
   /* if the same pointer */
@@ -1402,7 +1477,7 @@ isiCodeEqual (iCode * left, iCode * right)
          if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
            return 0;
        }
-      
+
       return 1;
     }
   return 0;
@@ -1451,7 +1526,7 @@ operandFromOperand (operand * op)
   nop->isLiteral = op->isLiteral;
   nop->usesDefs = op->usesDefs;
   nop->isParm = op->isParm;
-  
+
   switch (nop->type)
     {
     case SYMBOL:
@@ -1525,18 +1600,17 @@ operandFromSymbol (symbol * sym)
     ok = 0;
 
   if (!IS_AGGREGATE (sym->type) &&     /* not an aggregate */
-      !IS_FUNC (sym->type) &&  /* not a function   */
-      !sym->_isparm &&         /* not a parameter  */
-      sym->level &&            /* is a local variable */
-      !sym->addrtaken &&       /* whose address has not been taken */
-      !sym->reqv &&            /* does not already have a reg equivalence */
+      !IS_FUNC (sym->type) &&          /* not a function   */
+      !sym->_isparm &&                 /* not a parameter  */
+      IS_AUTO (sym) &&                 /* is a local auto variable */
+      !sym->addrtaken &&               /* whose address has not been taken */
+      !sym->reqv &&                    /* does not already have a reg equivalence */
       !IS_VOLATILE (sym->etype) &&     /* not declared as volatile */
-      !IS_STATIC (sym->etype) &&       /* and not declared static  */
-      !sym->islbl &&           /* not a label */
-      ok &&                    /* farspace check */
-      !IS_BITVAR (sym->etype)  /* not a bit variable */
+      !sym->islbl &&                   /* not a label */
+      ok &&                            /* farspace check */
+      !IS_BITVAR (sym->etype)          /* not a bit variable */
     )
-    {                                   
+    {
 
       /* we will use it after all optimizations
          and before liveRange calculation */
@@ -1665,7 +1739,7 @@ operandFromAst (ast * tree,int lvl)
     default:
       assert (0);
     }
-  
+
   /*  Just to keep the compiler happy */
   return (operand *) 0;
 }
@@ -1673,7 +1747,7 @@ operandFromAst (ast * tree,int lvl)
 /*-----------------------------------------------------------------*/
 /* setOperandType - sets the operand's type to the given type      */
 /*-----------------------------------------------------------------*/
-void 
+void
 setOperandType (operand * op, sym_link * type)
 {
   /* depending on the type of operand */
@@ -1714,7 +1788,7 @@ getArraySizePtr (operand * op)
   if(IS_PTR(ltype))
     {
       int size = getSize(ltype);
-      return(IS_GENPTR(ltype)?(size-1):size);
+      return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
     }
 
   if(IS_ARRAY(ltype))
@@ -1732,7 +1806,10 @@ getArraySizePtr (operand * op)
        case FUNCTION:
          return (FPTRSIZE);
        case GPOINTER:
-         return (GPTRSIZE-1);
+          if (GPTRSIZE > FPTRSIZE)
+           return (GPTRSIZE-1);
+          else
+           return (FPTRSIZE);
 
        default:
          return (FPTRSIZE);
@@ -1791,7 +1868,7 @@ usualBinaryConversions (operand ** op1, operand ** op2,
 
   *op1 = geniCodeCast (ctype, *op1, TRUE);
   *op2 = geniCodeCast (ctype, *op2, TRUE);
-       
+
   return ctype;
 }
 
@@ -1877,7 +1954,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
       geniCodeArray2Ptr (op);
       op->isaddr = 0;
     }
-    
+
   /* if the operand is already the desired type then do nothing */
   if (compareType (type, optype) == 1)
     return op;
@@ -1918,11 +1995,22 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
        }
       }
     } else { // from a pointer to a pointer
-      if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
+      if (IS_GENPTR(type) && IS_VOID(type->next))
+       { // cast to void* is always allowed
+       }
+      else if (IS_GENPTR(optype) && IS_VOID(optype->next))
+       { // cast from void* is always allowed
+       }
+      else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
        // if not a pointer to a function
        if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
          if (implicit) { // if not to generic, they have to match
-           if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
+           if (!IS_GENPTR(type) &&
+                !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
+                  ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
+                 )
+               )
+            {
              werror(E_INCOMPAT_PTYPES);
              errors++;
            }
@@ -1948,7 +2036,7 @@ 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      */
@@ -1982,9 +2070,10 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
   restype = getSpec (operandType (IC_RESULT (ic)));
   if (!IS_LITERAL(opetype) &&
       !IS_BIT(opetype))
+    {
       SPEC_SCLS (restype) = SPEC_SCLS (opetype);
-  SPEC_OCLS (restype) = SPEC_OCLS (opetype);
-
+      SPEC_OCLS (restype) = SPEC_OCLS (opetype);
+    }
   ADDTOCHAIN (ic);
   return IC_RESULT (ic);
 }
@@ -2049,8 +2138,8 @@ geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
   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)
+      && strcmp (port->target, "pic16") != 0  /* don't shift for pic */
+      && strcmp (port->target, "pic14") != 0)
     {
       if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
        {
@@ -2168,7 +2257,7 @@ subtractExit:
   if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
     return result;
   }
-  
+
   // should we really do this? is this ANSI?
   return geniCodeDivision (result,
                           operandFromLit (getSize (ltype->next)),
@@ -2299,7 +2388,7 @@ geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
 }
 
 /*-----------------------------------------------------------------*/
-/* aggrToPtr - changes an aggregate to pointer to an aggregate     */
+/* aggrToPtr - changes an "aggregate" to a "pointer to aggregate"  */
 /*-----------------------------------------------------------------*/
 sym_link *
 aggrToPtr (sym_link * type, bool force)
@@ -2320,6 +2409,19 @@ aggrToPtr (sym_link * type, bool force)
   return ptype;
 }
 
+/*------------------------------------------------------------------*/
+/* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
+/*------------------------------------------------------------------*/
+int
+aggrToPtrDclType (sym_link * type, bool force)
+{
+  if (IS_PTR (type) && !force)
+    return DCL_TYPE (type);
+
+  /* return the pointer depending on the storage class */
+  return PTR_TYPE (SPEC_OCLS (getSpec (type)));
+}
+
 /*-----------------------------------------------------------------*/
 /* geniCodeArray2Ptr - array to pointer                            */
 /*-----------------------------------------------------------------*/
@@ -2395,7 +2497,11 @@ geniCodeArray (operand * left, operand * right, int lvl)
                                      !IS_PTR (ltype->next))
                                     ? ltype : ltype->next), 0);
 
-  IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
+  if (!IS_AGGREGATE (ltype->next))
+    {
+      IC_RESULT (ic)->isaddr = 1;
+      IC_RESULT (ic)->aggr2ptr = 1;
+    }
   ADDTOCHAIN (ic);
 
   return IC_RESULT (ic);
@@ -2415,7 +2521,7 @@ geniCodeStruct (operand * left, operand * right, bool islval)
                                      right->operand.symOperand);
 
   wassert(IS_SYMOP(right));
-    
+
   /* add the offset */
   ic = newiCode ('+', left, operandFromLit (element->offset));
 
@@ -2428,10 +2534,10 @@ geniCodeStruct (operand * left, operand * right, bool islval)
   SPEC_OCLS (retype) = SPEC_OCLS (etype);
   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
   SPEC_CONST (retype) |= SPEC_CONST (etype);
-  
+
   if (IS_PTR (element->type))
     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
-  
+
   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
 
   ADDTOCHAIN (ic);
@@ -2467,9 +2573,11 @@ geniCodePostInc (operand * op)
   if (IS_ITEMP (rv))
     OP_SYMBOL(rv)->noSpilLoc = 1;
 
-  geniCodeAssign (rOp, rv, 0);
+  geniCodeAssign (rOp, rv, 0, 0);
 
   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
+  if (size == 0)
+    werror(W_SIZEOF_VOID);
   if (IS_FLOAT (rvtype))
     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
   else
@@ -2478,7 +2586,7 @@ geniCodePostInc (operand * op)
   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
   ADDTOCHAIN (ic);
 
-  geniCodeAssign (op, result, 0);
+  geniCodeAssign (op, result, 0, 0);
 
   return rOp;
 
@@ -2505,8 +2613,9 @@ geniCodePreInc (operand * op, bool lvalue)
       return op;
     }
 
-
   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
+  if (size == 0)
+    werror(W_SIZEOF_VOID);
   if (IS_FLOAT (roptype))
     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
   else
@@ -2514,8 +2623,8 @@ geniCodePreInc (operand * op, bool lvalue)
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-  (void) geniCodeAssign (op, result, 0);
-  if (lvalue || IS_TRUE_SYMOP (op))
+  (void) geniCodeAssign (op, result, 0, 0);
+  if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
     return op;
   else
     return result;
@@ -2550,9 +2659,11 @@ geniCodePostDec (operand * op)
   if (IS_ITEMP (rv))
     OP_SYMBOL(rv)->noSpilLoc = 1;
 
-  geniCodeAssign (rOp, rv, 0);
+  geniCodeAssign (rOp, rv, 0, 0);
 
   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
+  if (size == 0)
+    werror(W_SIZEOF_VOID);
   if (IS_FLOAT (rvtype))
     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
   else
@@ -2561,7 +2672,7 @@ geniCodePostDec (operand * op)
   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
   ADDTOCHAIN (ic);
 
-  geniCodeAssign (op, result, 0);
+  geniCodeAssign (op, result, 0, 0);
 
   return rOp;
 
@@ -2588,8 +2699,9 @@ geniCodePreDec (operand * op, bool lvalue)
       return op;
     }
 
-
   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
+  if (size == 0)
+    werror(W_SIZEOF_VOID);
   if (IS_FLOAT (roptype))
     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
   else
@@ -2597,8 +2709,8 @@ geniCodePreDec (operand * op, bool lvalue)
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-  (void) geniCodeAssign (op, result, 0);
-  if (lvalue || IS_TRUE_SYMOP (op))
+  (void) geniCodeAssign (op, result, 0, 0);
+  if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
     return op;
   else
     return result;
@@ -2641,7 +2753,7 @@ geniCodeAddressOf (operand * op)
       op->isaddr = 0;
       return op;
     }
-  
+
   /* lvalue check already done in decorateType */
   /* this must be a lvalue */
 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
@@ -2674,7 +2786,7 @@ geniCodeAddressOf (operand * op)
 /*-----------------------------------------------------------------*/
 /* setOClass - sets the output class depending on the pointer type */
 /*-----------------------------------------------------------------*/
-void 
+void
 setOClass (sym_link * ptr, sym_link * spec)
 {
   switch (DCL_TYPE (ptr))
@@ -2748,7 +2860,7 @@ geniCodeDerefPtr (operand * op,int lvl)
       /* outputclass needs 2b updated */
       setOClass (optype, retype);
     }
-  
+
   op->isGptr = IS_GENPTR (optype);
 
   op->isaddr = (IS_PTR (rtype) ||
@@ -2817,7 +2929,7 @@ geniCodeRightShift (operand * left, operand * right)
 /*-----------------------------------------------------------------*/
 /* geniCodeLogic- logic code                                       */
 /*-----------------------------------------------------------------*/
-operand *
+static operand *
 geniCodeLogic (operand * left, operand * right, int op)
 {
   iCode *ic;
@@ -2849,7 +2961,7 @@ geniCodeLogic (operand * left, operand * right, int op)
             ic = setNextItem (iCodeChain);
         }
       /* if casting literal to generic pointer, then cast to rtype instead */
-      if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
+      if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
         {
           left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
           ltype = operandType(left);
@@ -2869,7 +2981,7 @@ geniCodeLogic (operand * left, operand * right, int op)
             ic = setNextItem (iCodeChain);
         }
       /* if casting literal to generic pointer, then cast to rtype instead */
-      if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
+      if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic)))
         {
           right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
           rtype = operandType(right);
@@ -2889,12 +3001,77 @@ geniCodeLogic (operand * left, operand * right, int op)
       op != NE_OP &&
       op != AND_OP &&
       op != OR_OP)
-    ic->supportRtn = 1;
+   ic->supportRtn = 1;
 
   ADDTOCHAIN (ic);
   return IC_RESULT (ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* geniCodeLogicAndOr - && || operations                           */
+/*-----------------------------------------------------------------*/
+static operand *
+geniCodeLogicAndOr (ast *tree, int lvl)
+{
+  iCode *ic;
+  symbol *falseLabel = newiTempLabel (NULL);
+  symbol *trueLabel  = newiTempLabel (NULL);
+  symbol *exitLabel  = newiTempLabel (NULL);
+  operand *op, *result, *condition;
+
+  /* AND_OP and OR_OP are no longer generated because of bug-905492.
+     They can be reenabled by executing the following block. If you find
+     a decent optimization you could start right here:
+  */
+#if 0
+  if (0)
+    {
+       operand *leftOp, *rightOp;
+
+       leftOp  = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
+       rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
+
+       return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+    }
+#endif
+
+  /* generate two IFX for the '&&' or '||' op */
+
+  /* evaluate left operand */
+  condition = ast2iCode (tree->left, lvl + 1);
+  op = geniCodeRValue (condition, FALSE);
+
+  /* test left operand */
+  if (tree->opval.op == AND_OP)
+    ic = newiCodeCondition (op, NULL, falseLabel);
+  else /* OR_OP */
+    ic = newiCodeCondition (op, trueLabel, NULL);
+  ADDTOCHAIN (ic);
+
+  /* evaluate right operand */
+  condition = ast2iCode (tree->right, lvl + 1);
+  op = geniCodeRValue (condition, FALSE);
+
+  /* test right operand */
+  ic = newiCodeCondition (op, trueLabel, NULL);
+  ADDTOCHAIN (ic);
+
+  /* store 0 or 1 in result */
+  result = newiTempOperand (newCharLink(), 1);
+
+  geniCodeLabel (falseLabel);
+  geniCodeAssign (result, operandFromLit (0), 0, 0);
+  /* generate an unconditional goto */
+  geniCodeGoto (exitLabel);
+
+  geniCodeLabel (trueLabel);
+  geniCodeAssign (result, operandFromLit (1), 0, 0);
+
+  geniCodeLabel (exitLabel);
+
+  return result;
+}
+
 /*-----------------------------------------------------------------*/
 /* geniCodeUnary - for a a generic unary operation                 */
 /*-----------------------------------------------------------------*/
@@ -2928,7 +3105,7 @@ geniCodeConditional (ast * tree,int lvl)
 
   /* move the value to a new Operand */
   result = newiTempOperand (tree->right->ftype, 0);
-  geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
+  geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
 
   /* generate an unconditional goto */
   geniCodeGoto (exitLabel);
@@ -2937,7 +3114,7 @@ geniCodeConditional (ast * tree,int lvl)
   geniCodeLabel (falseLabel);
 
   false = ast2iCode (tree->right->right,lvl+1);
-  geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
+  geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
 
   /* create the exit label */
   geniCodeLabel (exitLabel);
@@ -2949,13 +3126,13 @@ geniCodeConditional (ast * tree,int lvl)
 /* geniCodeAssign - generate code for assignment                   */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeAssign (operand * left, operand * right, int nosupdate)
+geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
 {
   iCode *ic;
   sym_link *ltype = operandType (left);
   sym_link *rtype = operandType (right);
 
-  if (!left->isaddr && !IS_ITEMP (left))
+  if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
     {
       werror (E_LVALUE_REQUIRED, "assignment");
       return left;
@@ -2965,7 +3142,7 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
      check if the literal value is within bounds */
   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
     {
-      checkConstantRange(ltype, 
+      checkConstantRange(ltype,
                         OP_VALUE(right), "= operation", 0);
     }
 
@@ -3028,7 +3205,7 @@ geniCodeDummyRead (operand * op)
 
   if (!IS_VOLATILE(type))
     return;
-    
+
   ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
   ADDTOCHAIN (ic);
 
@@ -3038,7 +3215,7 @@ geniCodeDummyRead (operand * op)
 /*-----------------------------------------------------------------*/
 /* geniCodeSEParms - generate code for side effecting fcalls       */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeSEParms (ast * parms,int lvl)
 {
   if (!parms)
@@ -3061,9 +3238,9 @@ geniCodeSEParms (ast * parms,int lvl)
       IS_ADDRESS_OF_OP (parms->right))
     parms->right->left->lvalue = 1;
 
-  parms->opval.oprnd = 
+  parms->opval.oprnd =
     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
-               
+
   parms->type = EX_OPERAND;
   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
                SPEC_ARGREG(parms->ftype);
@@ -3073,7 +3250,7 @@ geniCodeSEParms (ast * parms,int lvl)
 /* geniCodeParms - generates parameters                            */
 /*-----------------------------------------------------------------*/
 value *
-geniCodeParms (ast * parms, value *argVals, int *stack, 
+geniCodeParms (ast * parms, value *argVals, int *stack,
               sym_link * ftype, int lvl)
 {
   iCode *ic;
@@ -3104,12 +3281,12 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
       /* hack don't like this but too lazy to think of
          something better */
       if (IS_ADDRESS_OF_OP (parms))
-       parms->left->lvalue = 1;
+        parms->left->lvalue = 1;
 
       if (IS_CAST_OP (parms) &&
-         IS_PTR (parms->ftype) &&
-         IS_ADDRESS_OF_OP (parms->right))
-       parms->right->left->lvalue = 1;
+          IS_PTR (parms->ftype) &&
+          IS_ADDRESS_OF_OP (parms->right))
+        parms->right->left->lvalue = 1;
 
       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
     }
@@ -3127,24 +3304,24 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
     {
       /* now decide whether to push or assign */
       if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
-       {
+        {
 
-         /* assign */
-         operand *top = operandFromSymbol (argVals->sym);
-         /* clear useDef and other bitVectors */
-         OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
-         geniCodeAssign (top, pval, 1);
-       }
+          /* assign */
+          operand *top = operandFromSymbol (argVals->sym);
+          /* clear useDef and other bitVectors */
+          OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
+          geniCodeAssign (top, pval, 1, 0);
+        }
       else
-       {
-         sym_link *p = operandType (pval);
-         /* push */
-         ic = newiCode (IPUSH, pval, NULL);
-         ic->parmPush = 1;
-         /* update the stack adjustment */
-         *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
-         ADDTOCHAIN (ic);
-       }
+        {
+          sym_link *p = operandType (pval);
+          /* push */
+          ic = newiCode (IPUSH, pval, NULL);
+          ic->parmPush = 1;
+          /* update the stack adjustment */
+          *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
+          ADDTOCHAIN (ic);
+        }
     }
 
   argVals=argVals->next;
@@ -3163,7 +3340,7 @@ geniCodeCall (operand * left, ast * parms,int lvl)
   sym_link *ftype;
   int stack = 0;
 
-  if (!IS_FUNC(OP_SYMBOL(left)->type) && 
+  if (!IS_FUNC(OP_SYMBOL(left)->type) &&
       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
     werror (E_FUNCTION_EXPECTED);
     return operandFromValue(valueFromLit(0));
@@ -3177,7 +3354,7 @@ geniCodeCall (operand * left, ast * parms,int lvl)
   ftype = operandType (left);
   if (IS_CODEPTR (ftype))
     ftype = ftype->next;
-    
+
   /* first the parameters */
   geniCodeParms (parms, NULL, &stack, ftype, lvl);
 
@@ -3204,9 +3381,11 @@ geniCodeCall (operand * left, ast * parms,int lvl)
 /*-----------------------------------------------------------------*/
 /* geniCodeReceive - generate intermediate code for "receive"      */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeReceive (value * args)
 {
+  unsigned char paramByteCounter = 0;
+
   /* for all arguments that are passed in registers */
   while (args)
     {
@@ -3240,13 +3419,24 @@ geniCodeReceive (value * args)
                }
            }
 
-         ic = newiCode (RECEIVE, NULL, NULL);    
+         ic = newiCode (RECEIVE, NULL, NULL);
          ic->argreg = SPEC_ARGREG(args->etype);
          if (first) {
              currFunc->recvSize = getSize (sym->type);
              first = 0;
          }
          IC_RESULT (ic) = opr;
+
+         /* misuse of parmBytes (normally used for functions)
+          * to save estimated stack position of this argument.
+          * Normally this should be zero for RECEIVE iCodes.
+          * No idea if this causes side effects on other ports. - dw
+          */
+         ic->parmBytes = paramByteCounter;
+
+         /* what stack position do we have? */
+         paramByteCounter += getSize (sym->type);
+
          ADDTOCHAIN (ic);
        }
 
@@ -3257,7 +3447,7 @@ geniCodeReceive (value * args)
 /*-----------------------------------------------------------------*/
 /* geniCodeFunctionBody - create the function body                 */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeFunctionBody (ast * tree,int lvl)
 {
   iCode *ic;
@@ -3283,6 +3473,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
   /* create a proc icode */
   ic = newiCode (FUNCTION, func, NULL);
   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
+  ic->tree = tree;
 
   ADDTOCHAIN (ic);
 
@@ -3298,6 +3489,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
 
   /* now generate the end proc */
   ic = newiCode (ENDFUNCTION, func, NULL);
+  ic->tree = tree;
   ADDTOCHAIN (ic);
   return;
 }
@@ -3305,7 +3497,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
 /*-----------------------------------------------------------------*/
 /* geniCodeReturn - gen icode for 'return' statement               */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeReturn (operand * op)
 {
   iCode *ic;
@@ -3321,7 +3513,7 @@ geniCodeReturn (operand * op)
 /*-----------------------------------------------------------------*/
 /* geniCodeIfx - generates code for extended if statement          */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeIfx (ast * tree,int lvl)
 {
   iCode *ic;
@@ -3380,10 +3572,11 @@ exit:
 /*-----------------------------------------------------------------*/
 /* geniCodeJumpTable - tries to create a jump table for switch     */
 /*-----------------------------------------------------------------*/
-int 
+int
 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
 {
-  int min = 0, max = 0, t, cnt = 0;
+  int min, max, cnt = 1;
+  int i, t;
   value *vch;
   iCode *ic;
   operand *boundary;
@@ -3391,6 +3584,10 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   set *labels = NULL;
   int needRangeCheck = !optimize.noJTabBoundary
                        || tree->values.switchVals.swDefault;
+  sym_link *cetype = getSpec (operandType (cond));
+  int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
+  int sizeofMatchJump, sizeofJumpTable;
+  int sizeIndex;
 
   if (!tree || !caseVals)
     return 0;
@@ -3398,50 +3595,115 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* the criteria for creating a jump table is */
   /* all integer numbers between the maximum & minimum must */
   /* be present , the maximum value should not exceed 255 */
-  min = max = (int) floatFromVal (vch = caseVals);
-  SNPRINTF (buffer, sizeof(buffer), 
-           "_case_%d_%d",
-          tree->values.switchVals.swNum,
-          min);
-  addSet (&labels, newiTempLabel (buffer));
-
-  /* if there is only one case value then no need */
-  if (!(vch = vch->next))
-    return 0;
+  /* If not all integer numbers are present the algorithm */
+  /* inserts jumps to the default label for the missing numbers */
+  /* and decides later whether it is worth it */
+  min = (int) floatFromVal (vch = caseVals);
 
-  while (vch)
+  while (vch->next)
     {
-      if (((t = (int) floatFromVal (vch)) - max) != 1)
-       return 0;
-      SNPRINTF (buffer, sizeof(buffer), 
-               "_case_%d_%d",
-              tree->values.switchVals.swNum,
-              t);
-      addSet (&labels, newiTempLabel (buffer));
-      max = t;
       cnt++;
       vch = vch->next;
     }
+  max = (int) floatFromVal (vch);
 
-  /* if the number of case statements <= 2 then */
-  /* it is not economical to create the jump table */
-  /* since two compares are needed for boundary conditions */
-  if ((needRangeCheck && cnt <= 2) || max > (255 / 3))
+  /* Exit if the range is too large to handle with a jump table. */
+  if (1 + max - min > port->jumptableCost.maxCount)
     return 0;
 
+  switch (getSize (operandType (cond)))
+    {
+    case 1: sizeIndex = 0; break;
+    case 2: sizeIndex = 1; break;
+    case 4: sizeIndex = 2; break;
+    default: return 0;
+    }
+
+  /* Compute the size cost of the range check and subtraction. */
+  sizeofMinCost = 0;
+  sizeofZeroMinCost = 0;
+  sizeofMaxCost = 0;
+  if (needRangeCheck)
+    {
+      if (!(min==0 && IS_UNSIGNED (cetype)))
+        sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+      if (!IS_UNSIGNED (cetype))
+        sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+      sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+    }
+  if (min)
+    sizeofMinCost += port->jumptableCost.sizeofSubtract;
+
+  /* If the size cost of handling a non-zero minimum exceeds the */
+  /* cost of extending the range down to zero, then it might be */
+  /* better to extend the range to zero. */
+  if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
+                 >= (min * port->jumptableCost.sizeofElement))
+    {
+      /* Only extend the jump table if it would still be manageable. */
+      if (1 + max <= port->jumptableCost.maxCount)
+        {
+          min = 0;
+          if (IS_UNSIGNED (cetype))
+            sizeofMinCost = 0;
+          else
+            sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
+        }
+    }
+
+  /* Compute the total size cost of a jump table. */
+  sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
+                     + port->jumptableCost.sizeofDispatch
+                     + sizeofMinCost + sizeofMaxCost;
+
+  /* Compute the total size cost of a match & jump sequence */
+  sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
+
+  /* If the size cost of the jump table is uneconomical then exit */
+  if (sizeofMatchJump <  sizeofJumpTable)
+    return 0;
+
+  /* The jump table is preferable. */
+
+  /* First, a label for the default or missing cases. */
   if (tree->values.switchVals.swDefault)
     {
-       SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+      SNPRINTF (buffer, sizeof(buffer),
+                "_default_%d",
+                tree->values.switchVals.swNum);
     }
   else
     {
-       SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+      SNPRINTF (buffer, sizeof(buffer),
+                "_swBrk_%d",
+                tree->values.switchVals.swNum);
     }
-    
-
   falseLabel = newiTempLabel (buffer);
 
-  /* so we can create a jumptable */
+  /* Build the list of labels for the jump table. */
+  vch = caseVals;
+  t = (int) floatFromVal (vch);
+  for (i=min; i<=max; i++)
+    {
+      if (vch && t==i)
+        {
+          /* Explicit case: make a new label for it. */
+          SNPRINTF (buffer, sizeof(buffer),
+                    "_case_%d_%d",
+                    tree->values.switchVals.swNum,
+                    i);
+          addSet (&labels, newiTempLabel (buffer));
+          vch = vch->next;
+          if (vch)
+            t = (int) floatFromVal (vch);
+        }
+      else
+        {
+          /* Implicit case: use the default label. */
+          addSet (&labels, falseLabel);
+        }
+    }
+
   /* first we rule out the boundary conditions */
   /* if only optimization says so */
   if (needRangeCheck)
@@ -3488,13 +3750,13 @@ geniCodeSwitch (ast * tree,int lvl)
   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
   value *caseVals = tree->values.switchVals.swVals;
   symbol *trueLabel, *falseLabel;
-      
+
   /* If the condition is a literal, then just jump to the */
   /* appropriate case label. */
   if (IS_LITERAL(getSpec(operandType(cond))))
     {
       int switchVal, caseVal;
-      
+
       switchVal = (int) floatFromVal (cond->operand.valOperand);
       while (caseVals)
         {
@@ -3512,6 +3774,22 @@ geniCodeSwitch (ast * tree,int lvl)
       goto defaultOrBreak;
     }
 
+  /* If cond is volatile, it might change while we are trying to */
+  /* find the matching case. To avoid this possibility, make a   */
+  /* non-volatile copy to use instead. */
+  if (IS_OP_VOLATILE (cond))
+    {
+      operand * newcond;
+      iCode * ic;
+
+      newcond = newiTempOperand (operandType (cond), TRUE);
+      newcond->isvolatile = 0;
+      ic = newiCode ('=', NULL, cond);
+      IC_RESULT (ic) = newcond;
+      ADDTOCHAIN (ic);
+      cond = newcond;
+    }
+
   /* if we can make this a jump table */
   if (geniCodeJumpTable (cond, caseVals, tree))
     goto jumpTable;            /* no need for the comparison */
@@ -3556,7 +3834,7 @@ jumpTable:
 /*-----------------------------------------------------------------*/
 /* geniCodeInline - intermediate code for inline assembler         */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeInline (ast * tree)
 {
   iCode *ic;
@@ -3586,30 +3864,42 @@ geniCodeArrayInit (ast * tree, operand *array)
   }
   ADDTOCHAIN (ic);
 }
-       
+
 /*-----------------------------------------------------------------*/
 /* geniCodeCritical - intermediate code for a critical statement   */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeCritical (ast *tree, int lvl)
 {
   iCode *ic;
   operand *op = NULL;
+  sym_link *type;
+
+  if (!options.stackAuto)
+    {
+      type = newLink(SPECIFIER);
+      SPEC_VOLATILE(type) = 1;
+      SPEC_NOUN(type) = V_BIT;
+      SPEC_SCLS(type) = S_BIT;
+      SPEC_BLEN(type) = 1;
+      SPEC_BSTR(type) = 0;
+      op = newiTempOperand(type, 1);
+    }
 
   /* If op is NULL, the original interrupt state will saved on */
   /* the stack. Otherwise, it will be saved in op. */
-  
-  /* Generate a save of the current interrupt state & disabled */
+
+  /* Generate a save of the current interrupt state & disable */
   ic = newiCode (CRITICAL, NULL, NULL);
   IC_RESULT (ic) = op;
   ADDTOCHAIN (ic);
-  
+
   /* Generate the critical code sequence */
   if (tree->left && tree->left->type == EX_VALUE)
     geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
   else
     ast2iCode (tree->left,lvl+1);
-  
+
   /* Generate a restore of the original interrupt state */
   ic = newiCode (ENDCRITICAL, NULL, op);
   ADDTOCHAIN (ic);
@@ -3727,6 +4017,8 @@ ast2iCode (ast * tree,int lvl)
       tree->opval.op != '?' &&
       tree->opval.op != CALL &&
       tree->opval.op != IFX &&
+      tree->opval.op != AND_OP &&
+      tree->opval.op != OR_OP &&
       tree->opval.op != LABEL &&
       tree->opval.op != GOTO &&
       tree->opval.op != SWITCH &&
@@ -3905,28 +4197,29 @@ ast2iCode (ast * tree,int lvl)
        setOperandType (op, UCHARTYPE);
        return op;
       }
+    case AND_OP:
+    case OR_OP:
+      return geniCodeLogicAndOr (tree, lvl);
     case '>':
     case '<':
     case LE_OP:
     case GE_OP:
     case EQ_OP:
     case NE_OP:
-    case AND_OP:
-    case OR_OP:
       /* different compilers (even different gccs) evaluate
-        the two calls in a different order. to get the same
-        result on all machines we've to specify a clear sequence.
+         the two calls in a different order. to get the same
+         result on all machines we've to specify a clear sequence.
       return geniCodeLogic (geniCodeRValue (left, FALSE),
                             geniCodeRValue (right, FALSE),
                             tree->opval.op);
       */
       {
-       operand *leftOp, *rightOp;
+        operand *leftOp, *rightOp;
 
-       rightOp = geniCodeRValue (right, FALSE);
-       leftOp  = geniCodeRValue (left , FALSE);
+        leftOp  = geniCodeRValue (left , FALSE);
+        rightOp = geniCodeRValue (right, FALSE);
 
-       return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+        return geniCodeLogic (leftOp, rightOp, tree->opval.op);
       }
     case '?':
       return geniCodeConditional (tree,lvl);
@@ -3944,7 +4237,7 @@ ast2iCode (ast * tree,int lvl)
        else
          right = geniCodeRValue (right, FALSE);
 
-       geniCodeAssign (left, right, 0);
+       geniCodeAssign (left, right, 0, 1);
        return right;
       }
     case MUL_ASSIGN:
@@ -3952,8 +4245,9 @@ ast2iCode (ast * tree,int lvl)
        geniCodeAssign (left,
                geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE), FALSE),
-                                 getResultTypeFromType (tree->ftype));
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype)),
+                       0, 1);
 
     case DIV_ASSIGN:
       return
@@ -3962,7 +4256,7 @@ ast2iCode (ast * tree,int lvl)
                                                  FALSE),
                                  geniCodeRValue (right, FALSE),
                                  getResultTypeFromType (tree->ftype)),
-                       0);
+                       0, 1);
     case MOD_ASSIGN:
       return
        geniCodeAssign (left,
@@ -3970,7 +4264,7 @@ ast2iCode (ast * tree,int lvl)
                                                  FALSE),
                                  geniCodeRValue (right, FALSE),
                                  getResultTypeFromType (tree->ftype)),
-                       0);
+                       0, 1);
     case ADD_ASSIGN:
       {
        sym_link *rtype = operandType (right);
@@ -3988,7 +4282,7 @@ ast2iCode (ast * tree,int lvl)
                                  right,
                                  getResultTypeFromType (tree->ftype),
                                  lvl),
-                              0);
+                              0, 1);
       }
     case SUB_ASSIGN:
       {
@@ -4009,7 +4303,7 @@ ast2iCode (ast * tree,int lvl)
                                                  FALSE),
                                  right,
                                  getResultTypeFromType (tree->ftype)),
-                         0);
+                         0, 1);
       }
     case LEFT_ASSIGN:
       return
@@ -4018,13 +4312,13 @@ ast2iCode (ast * tree,int lvl)
                                                   ,FALSE),
                                   geniCodeRValue (right, FALSE),
                                   getResultTypeFromType (tree->ftype)),
-                       0);
+                       0, 1);
     case RIGHT_ASSIGN:
       return
        geniCodeAssign (left,
               geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
                                                   ,FALSE),
-                                  geniCodeRValue (right, FALSE)), 0);
+                                  geniCodeRValue (right, FALSE)), 0, 1);
     case AND_ASSIGN:
       return
        geniCodeAssign (left,
@@ -4032,7 +4326,7 @@ ast2iCode (ast * tree,int lvl)
                                                  FALSE),
                                  geniCodeRValue (right, FALSE),
                                  BITWISEAND,
-                                 operandType (left)), 0);
+                                 operandType (left)), 0, 1);
     case XOR_ASSIGN:
       return
        geniCodeAssign (left,
@@ -4040,7 +4334,7 @@ ast2iCode (ast * tree,int lvl)
                                                  FALSE),
                                  geniCodeRValue (right, FALSE),
                                  '^',
-                                 operandType (left)), 0);
+                                 operandType (left)), 0, 1);
     case OR_ASSIGN:
       return
        geniCodeAssign (left,
@@ -4048,7 +4342,7 @@ ast2iCode (ast * tree,int lvl)
                                                   ,FALSE),
                                   geniCodeRValue (right, FALSE),
                                   '|',
-                                  operandType (left)), 0);
+                                  operandType (left)), 0, 1);
     case ',':
       return geniCodeRValue (right, FALSE);
 
@@ -4082,11 +4376,11 @@ ast2iCode (ast * tree,int lvl)
     case INLINEASM:
       geniCodeInline (tree);
       return NULL;
-       
+
     case ARRAYINIT:
        geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
        return NULL;
-    
+
     case CRITICAL:
        geniCodeCritical (tree, lvl);
     }
@@ -4135,25 +4429,25 @@ static const char *opTypeToStr(OPTYPE op)
       case VALUE: return "value";
       case TYPE: return "type";
     }
-    return "undefined type";    
+    return "undefined type";
 }
 
 
-operand *validateOpType(operand        *op, 
+operand *validateOpType(operand        *op,
                        const char      *macro,
                        const char      *args,
                        OPTYPE          type,
-                       const char      *file, 
+                       const char      *file,
                        unsigned        line)
-{    
+{
     if (op && op->type == type)
     {
        return op;
     }
-    fprintf(stderr, 
+    fprintf(stderr,
            "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
            " expected %s, got %s\n",
-           macro, args, file, line, 
+           macro, args, file, line,
            opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
     exit(-1);
     return op; // never reached, makes compiler happy.