* sim/ucsim/configure.in,
[fw/sdcc] / src / SDCCicode.c
index 4ab359dc000872995b73e548e0cec1ef05681ae6..f4e50eba162c9333a736ee99c9196b129101bc24 100644 (file)
@@ -38,19 +38,21 @@ char *filename;
 int lineno;
 int block;
 int scopeLevel;
+int seqPoint;
 
 symbol *returnLabel;           /* function return label */
 symbol *entryLabel;            /* function entry  label */
 
 /*-----------------------------------------------------------------*/
 /* forward definition of some functions */
-operand *geniCodeDivision (operand *, operand *);
 operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *,int);
-operand *geniCodeArray2Ptr (operand *);
+static operand *geniCodeArray (operand *, operand *,int);
+static operand *geniCodeArray2Ptr (operand *);
 operand *geniCodeRValue (operand *, bool);
 operand *geniCodeDerefPtr (operand *,int);
 int isLvaluereq(int lvl);
+void  setOClass (sym_link * ptr, sym_link * spec);
+static operand *geniCodeCast (sym_link *, operand *, bool);
 
 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
 /* forward definition of ic print functions */
@@ -67,6 +69,9 @@ PRINTFUNC (picIfx);
 PRINTFUNC (picJumpTable);
 PRINTFUNC (picInline);
 PRINTFUNC (picReceive);
+PRINTFUNC (picDummyRead);
+PRINTFUNC (picCritical);
+PRINTFUNC (picEndCritical);
 
 iCodeTable codeTable[] =
 {
@@ -113,32 +118,16 @@ iCodeTable codeTable[] =
   {RECEIVE, "recv", picReceive, NULL},
   {SEND, "send", picGenericOne, NULL},
   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
+  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
+  {CRITICAL, "critical_start", picCritical, NULL},
+  {ENDCRITICAL, "critical_end", picEndCritical, NULL}
 };
 
-// this makes it more easy to catch bugs
-struct bitVect *OP_DEFS(struct operand *op) {
-  assert (IS_SYMOP(op));
-  return OP_SYMBOL(op)->defs;
-}
-struct bitVect *OP_DEFS_SET(struct operand *op, struct bitVect *bv) {
-  assert (IS_SYMOP(op));
-  OP_SYMBOL(op)->defs=bv;
-  return bv;
-}
-struct bitVect *OP_USES(struct operand *op) {
-  assert (IS_SYMOP(op));
-  return OP_SYMBOL(op)->uses;
-}
-struct bitVect *OP_USES_SET(struct operand *op, struct bitVect *bv) {
-  assert (IS_SYMOP(op));
-  OP_SYMBOL(op)->uses=bv;
-  return bv;
-}
-
 /*-----------------------------------------------------------------*/
 /* checkConstantRange: check a constant against the type           */
 /*-----------------------------------------------------------------*/
 
+
 /*   pedantic=0: allmost anything is allowed as long as the absolute
        value is within the bit range of the type, and -1 is treated as
        0xf..f for unsigned types (e.g. in assign)
@@ -146,7 +135,7 @@ struct bitVect *OP_USES_SET(struct operand *op, struct bitVect *bv) {
      pedantic>1: "char c=200" is not allowed (evaluates to -56)
 */
 
-void checkConstantRange(sym_link *ltype, value *val, char *msg, 
+void checkConstantRange(sym_link *ltype, value *val, char *msg,
                        int pedantic) {
   double max;
   int warnings=0;
@@ -155,14 +144,14 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg,
 
   max = pow ((double)2.0, (double)bitsForType(ltype));
 
-  if (SPEC_LONG(val->type)) {
-    if (SPEC_USIGN(val->type)) {
+  if (IS_LONG(val->type)) {
+    if (IS_UNSIGNED(val->type)) {
       v=SPEC_CVAL(val->type).v_ulong;
     } else {
       v=SPEC_CVAL(val->type).v_long;
     }
   } else {
-    if (SPEC_USIGN(val->type)) {
+    if (IS_UNSIGNED(val->type)) {
       v=SPEC_CVAL(val->type).v_uint;
     } else {
       v=SPEC_CVAL(val->type).v_int;
@@ -176,21 +165,21 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg,
     pedantic=2;
 #endif
 
-  if (SPEC_NOUN(ltype)==FLOAT) {
+  if (IS_FLOAT(ltype)) {
     // anything will do
     return;
   }
 
-  if (!SPEC_USIGN(val->type) && v<0) {
+  if (!IS_UNSIGNED(val->type) && v<0) {
     negative=1;
-    if (SPEC_USIGN(ltype) && (pedantic>1)) {
+    if (IS_UNSIGNED(ltype) && (pedantic>1)) {
       warnings++;
     }
     v=-v;
   }
 
   // if very pedantic: "char c=200" is not allowed
-  if (pedantic>1 && !SPEC_USIGN(ltype)) {
+  if (pedantic>1 && !IS_UNSIGNED(ltype)) {
     max = max/2 + negative;
   }
 
@@ -200,8 +189,8 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg,
 
 #if 0 // temporary disabled, leaving the warning as a reminder
   if (warnings) {
-    sprintf (message, "for %s %s in %s", 
-            SPEC_USIGN(ltype) ? "unsigned" : "signed",
+    SNPRINTF (message, sizeof(message), "for %s %s in %s", 
+            IS_UNSIGNED(ltype) ? "unsigned" : "signed",
             nounName(ltype), msg);
     werror (W_CONST_RANGE, message);
 
@@ -233,10 +222,10 @@ printOperand (operand * op, FILE * file)
 
     case VALUE:
       opetype = getSpec (operandType (op));
-      if (SPEC_NOUN (opetype) == V_FLOAT)
+      if (IS_FLOAT (opetype))
        fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
       else
-       fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
+       fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
       printTypeChain (operandType (op), file);
       fprintf (file, "}");
       break;
@@ -481,10 +470,40 @@ PRINTFUNC (picReceive)
   fprintf (of, "\n");
 }
 
+PRINTFUNC (picDummyRead)
+{
+  fprintf (of, "\t");
+  fprintf (of, "%s ", s);
+  printOperand (IC_RIGHT (ic), of);
+  fprintf (of, "\n");
+}
+
+PRINTFUNC (picCritical)
+{
+  fprintf (of, "\t");
+  if (IC_RESULT (ic))
+    printOperand (IC_RESULT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, " = %s ", s);
+  fprintf (of, "\n");
+}
+
+PRINTFUNC (picEndCritical)
+{
+  fprintf (of, "\t");
+  fprintf (of, "%s = ", s);
+  if (IC_RIGHT (ic))
+    printOperand (IC_RIGHT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, "\n");
+}
+
 /*-----------------------------------------------------------------*/
 /* piCode - prints one iCode                                       */
 /*-----------------------------------------------------------------*/
-int 
+int
 piCode (void *item, FILE * of)
 {
   iCode *ic = item;
@@ -508,7 +527,7 @@ void PICC(iCode *ic)
 /*-----------------------------------------------------------------*/
 /* printiCChain - prints intermediate code for humans              */
 /*-----------------------------------------------------------------*/
-void 
+void
 printiCChain (iCode * icChain, FILE * of)
 {
   iCode *loop;
@@ -520,7 +539,7 @@ printiCChain (iCode * icChain, FILE * of)
     {
       if ((icTab = getTableEntry (loop->op)))
        {
-         fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
+         fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
                   loop->filename, loop->lineno,
                   loop->seq, loop->key, loop->depth, loop->supportRtn);
 
@@ -554,6 +573,7 @@ newiCode (int op, operand * left, operand * right)
 
   ic = Safe_alloc ( sizeof (iCode));
 
+  ic->seqPoint = seqPoint;
   ic->lineno = lineno;
   ic->filename = filename;
   ic->block = block;
@@ -597,7 +617,7 @@ newiCodeLabelGoto (int op, symbol * label)
 
   ic = newiCode (op, NULL, NULL);
   ic->op = op;
-  ic->argLabel.label = label;
+  ic->label = label;
   IC_LEFT (ic) = NULL;
   IC_RIGHT (ic) = NULL;
   IC_RESULT (ic) = NULL;
@@ -613,11 +633,16 @@ newiTemp (char *s)
   symbol *itmp;
 
   if (s)
-    sprintf (buffer, "%s", s);
+  {
+      SNPRINTF (buffer, sizeof(buffer), "%s", s);
+  }
   else
-    sprintf (buffer, "iTemp%d", iTempNum++);
+  {
+      SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
+  }
+    
   itmp = newSymbol (buffer, 1);
-  strcpy (itmp->rname, itmp->name);
+  strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
   itmp->isitmp = 1;
 
   return itmp;
@@ -636,10 +661,12 @@ newiTempLabel (char *s)
     return itmplbl;
 
   if (s)
-    itmplbl = newSymbol (s, 1);
+    {
+       itmplbl = newSymbol (s, 1);
+    }
   else
     {
-      sprintf (buffer, "iTempLbl%d", iTempLblNum++);
+      SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
       itmplbl = newSymbol (buffer, 1);
     }
 
@@ -658,7 +685,7 @@ newiTempPreheaderLabel ()
 {
   symbol *itmplbl;
 
-  sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
+  SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
   itmplbl = newSymbol (buffer, 1);
 
   itmplbl->isitmp = 1;
@@ -735,7 +762,7 @@ copyiCode (iCode * ic)
 iCodeTable *
 getTableEntry (int oper)
 {
-  int i;
+  unsigned i;
 
   for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
     if (oper == codeTable[i].icode)
@@ -812,6 +839,8 @@ isParameterToCall (value * args, operand * op)
 {
   value *tval = args;
 
+  wassert (IS_SYMOP(op));
+    
   while (tval)
     {
       if (tval->sym &&
@@ -834,7 +863,7 @@ isOperandGlobal (operand * op)
   if (IS_ITEMP (op))
     return 0;
 
-  if (op->type == SYMBOL &&
+  if (IS_SYMOP(op) &&
       (op->operand.symOperand->level == 0 ||
        IS_STATIC (op->operand.symOperand->etype) ||
        IS_EXTERN (op->operand.symOperand->etype))
@@ -857,13 +886,13 @@ 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; 
 }
 
 /*-----------------------------------------------------------------*/
@@ -994,10 +1023,25 @@ isOperandOnStack (operand * op)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/* isOclsExpensive - will return true if accesses to an output     */
+/*                   storage class are expensive                   */
+/*-----------------------------------------------------------------*/
+bool 
+isOclsExpensive (struct memmap *oclass)
+{
+  if (port->oclsExpense)
+    return port->oclsExpense (oclass) > 0;
+
+  /* In the absence of port specific guidance, assume only */
+  /* farspace is expensive. */
+  return IN_FARSPACE (oclass);
+}
+
 /*-----------------------------------------------------------------*/
 /* operandLitValue - literal value of an operand                   */
 /*-----------------------------------------------------------------*/
-double 
+double
 operandLitValue (operand * op)
 {
   assert (isOperandLiteral (op));
@@ -1021,7 +1065,7 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
        ic = ic->next;
        (*pcount)++;
     }
-    
+
     ic->generated = 1;
     /* make sure this is a builtin function call */
     assert(IS_SYMOP(IC_LEFT(ic)));
@@ -1031,7 +1075,7 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
 }
 
 /*-----------------------------------------------------------------*/
-/* operandOperation - perforoms operations on operands             */
+/* operandOperation - performs operations on operands             */
 /*-----------------------------------------------------------------*/
 operand *
 operandOperation (operand * left, operand * right,
@@ -1039,12 +1083,12 @@ operandOperation (operand * left, operand * right,
 {
   sym_link *let , *ret=NULL;
   operand *retval = (operand *) 0;
-  
+
   assert (isOperandLiteral (left));
   let = getSpec(operandType(left));
   if (right) {
     assert (isOperandLiteral (right));
-    ret = getSpec(operandType(left));
+    ret = getSpec(operandType(right));
   }
 
   switch (op)
@@ -1060,68 +1104,146 @@ operandOperation (operand * left, operand * right,
                                                 operandLitValue (right)));
       break;
     case '*':
+      /*
       retval = operandFromValue (valCastLiteral (type,
                                                 operandLitValue (left) *
                                                 operandLitValue (right)));
+      This could be all we've to do, but with gcc we've to take care about
+      overflows. Two examples:
+      ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
+      significant bits are lost (52 in fraction, 63 bits would be
+      necessary to keep full precision).
+      If the resulting double value is greater than ULONG_MAX (resp.
+      USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
+      */
+
+      /* if it is not a specifier then we can assume that */
+      /* it will be an unsigned long                      */
+      if (IS_INT (type) ||
+          !IS_SPEC (type))
+        {
+         /* long is handled here, because it can overflow with double */
+         if (IS_LONG (type) ||
+             !IS_SPEC (type))
+         /* signed and unsigned mul are the same, as long as the precision
+            of the result isn't bigger than the precision of the operands. */
+           retval = operandFromValue (valCastLiteral (type,
+                    (TYPE_UDWORD) operandLitValue (left) *
+                    (TYPE_UDWORD) operandLitValue (right)));
+         else if (IS_UNSIGNED (type)) /* unsigned int */
+           {
+             /* unsigned int is handled here in order to detect overflow */
+             TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
+                              (TYPE_UWORD) operandLitValue (right);
+
+             retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
+             if (ul != (TYPE_UWORD) ul)
+               werror (W_INT_OVL);
+           }
+         else /* signed int */
+           {
+             /* signed int is handled here in order to detect overflow */
+             TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
+                            (TYPE_WORD) operandLitValue (right);
+
+             retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
+             if (l != (TYPE_WORD) l)
+               werror (W_INT_OVL);
+           }
+       }
+      else
+       /* all others go here: */
+       retval = operandFromValue (valCastLiteral (type,
+                                                  operandLitValue (left) *
+                                                  operandLitValue (right)));
       break;
     case '/':
-      if ((unsigned long) operandLitValue (right) == 0)
+      if ((TYPE_UDWORD) operandLitValue (right) == 0)
        {
          werror (E_DIVIDE_BY_ZERO);
          retval = right;
 
        }
       else
-       retval = operandFromValue (valCastLiteral (type,
-                                                  operandLitValue (left) /
-                                                  operandLitValue (right)));
+        {
+         if (IS_UNSIGNED (type))
+           {
+             SPEC_USIGN (let) = 1;
+             SPEC_USIGN (ret) = 1;
+             retval = operandFromValue (valCastLiteral (type,
+                                       (TYPE_UDWORD) operandLitValue (left) /
+                                       (TYPE_UDWORD) operandLitValue (right)));
+           }
+         else
+           {
+              retval = operandFromValue (valCastLiteral (type,
+                                                    operandLitValue (left) /
+                                                    operandLitValue (right)));
+           }
+       }
       break;
     case '%':
-      if ((unsigned long) operandLitValue (right) == 0) {
+      if ((TYPE_UDWORD) operandLitValue (right) == 0)
+        {
          werror (E_DIVIDE_BY_ZERO);
          retval = right;
-      }
-      else 
-       retval = operandFromLit ((SPEC_USIGN(let) ? 
-                                 (unsigned long) operandLitValue (left) :
-                                 (long) operandLitValue (left)) %
-                                (SPEC_USIGN(ret) ? 
-                                 (unsigned long) operandLitValue (right) :
-                                 (long) operandLitValue (right)));
-
+        }
+      else
+        {
+          if (IS_UNSIGNED (type))
+           retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
+                                    (TYPE_UDWORD) operandLitValue (right));
+         else
+           retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
+                                    (TYPE_DWORD) operandLitValue (right));
+        }
       break;
     case LEFT_OP:
-      retval = operandFromLit ((SPEC_USIGN(let) ? 
-                                 (unsigned long) operandLitValue (left) :
-                                 (long) operandLitValue (left)) <<
-                                (SPEC_USIGN(ret) ? 
-                                 (unsigned long) operandLitValue (right) :
-                                 (long) operandLitValue (right)));
+      /* The number of left shifts is always unsigned. Signed doesn't make
+        sense here. Shifting by a negative number is impossible. */
+      retval = operandFromValue (valCastLiteral (type,
+                                ((TYPE_UDWORD) operandLitValue (left) <<
+                                 (TYPE_UDWORD) operandLitValue (right))));
       break;
-    case RIGHT_OP: {
-      double lval = operandLitValue(left), rval = operandLitValue(right);
-      double res=0;
-      switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0)) 
-       {
-       case 0: // left=unsigned right=unsigned
-         res=(unsigned long)lval >> (unsigned long)rval;
-         break;
-       case 1: // left=unsigned right=signed
-         res=(unsigned long)lval >> (signed long)rval;
-         break;
-       case 2: // left=signed right=unsigned
-         res=(signed long)lval >> (unsigned long)rval;
-         break;
-       case 3: // left=signed right=signed
-         res=(signed long)lval >> (signed long)rval;
-         break;
-       }
-      retval = operandFromLit (res);
+    case RIGHT_OP:
+      /* The number of right shifts is always unsigned. Signed doesn't make
+        sense here. Shifting by a negative number is impossible. */
+      if (IS_UNSIGNED(let))
+        /* unsigned: logic shift right */
+        retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
+                                (TYPE_UDWORD) operandLitValue (right));
+      else
+        /* signed: arithmetic shift right */
+        retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
+                                (TYPE_UDWORD) operandLitValue (right));
       break;
-    }
     case EQ_OP:
-      retval = operandFromLit (operandLitValue (left) ==
-                              operandLitValue (right));
+      if (IS_FLOAT (let) ||
+          IS_FLOAT (ret))
+       {
+         retval = operandFromLit (operandLitValue (left) ==
+                                  operandLitValue (right));
+       }
+      else
+       {
+         /* this op doesn't care about signedness */
+         TYPE_UDWORD l, r;
+
+         l = (TYPE_UDWORD) operandLitValue (left);
+         r = (TYPE_UDWORD) operandLitValue (right);
+         /* In order to correctly compare 'signed int' and 'unsigned int' it's
+            neccessary to strip them to 16 bit.
+            Literals are reduced to their cheapest type, therefore left and
+            right might have different types. It's neccessary to find a
+            common type: int (used for char too) or long */
+         if (!IS_LONG (let) &&
+             !IS_LONG (ret))
+           {
+             r = (TYPE_UWORD) r;
+             l = (TYPE_UWORD) l;
+           }
+         retval = operandFromLit (l == r);
+       }
       break;
     case '<':
       retval = operandFromLit (operandLitValue (left) <
@@ -1144,16 +1266,19 @@ operandOperation (operand * left, operand * right,
                               operandLitValue (right));
       break;
     case BITWISEAND:
-      retval = operandFromLit ((long)operandLitValue(left) & 
-                              (long)operandLitValue(right));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) &
+                                                (TYPE_UDWORD)operandLitValue(right)));
       break;
     case '|':
-      retval = operandFromLit ((long)operandLitValue (left) |
-                              (long)operandLitValue (right));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) |
+                                                (TYPE_UDWORD)operandLitValue(right)));
       break;
     case '^':
-      retval = operandFromLit ((long)operandLitValue (left) ^
-                              (long)operandLitValue (right));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) ^
+                                                (TYPE_UDWORD)operandLitValue(right)));
       break;
     case AND_OP:
       retval = operandFromLit (operandLitValue (left) &&
@@ -1165,7 +1290,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RRC:
       {
-       long i = (long) operandLitValue (left);
+       TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
 
        retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
                                 (i << 1));
@@ -1173,7 +1298,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RLC:
       {
-       long i = (long) operandLitValue (left);
+       TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
 
        retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
                                 (i >> 1));
@@ -1181,11 +1306,12 @@ operandOperation (operand * left, operand * right,
       break;
 
     case UNARYMINUS:
-      retval = operandFromLit (-1 * operandLitValue (left));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 -1 * operandLitValue (left)));
       break;
 
     case '~':
-      retval = operandFromLit (~((long) operandLitValue (left)));
+      retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
       break;
 
     case '!':
@@ -1205,7 +1331,7 @@ operandOperation (operand * left, operand * right,
 /*-----------------------------------------------------------------*/
 /* isOperandEqual - compares two operand & return 1 if they r =    */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandEqual (operand * left, operand * right)
 {
   /* if the pointers are equal then they are equal */
@@ -1325,7 +1451,7 @@ operandFromOperand (operand * op)
   nop->isLiteral = op->isLiteral;
   nop->usesDefs = op->usesDefs;
   nop->isParm = op->isParm;
-
+  
   switch (nop->type)
     {
     case SYMBOL:
@@ -1393,6 +1519,7 @@ operandFromSymbol (symbol * sym)
      register equivalent for a local symbol */
   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+      !TARGET_IS_HC08 &&
       (!(options.model == MODEL_FLAT24)) ) &&
       options.stackAuto == 0)
     ok = 0;
@@ -1409,12 +1536,13 @@ operandFromSymbol (symbol * sym)
       ok &&                    /* farspace check */
       !IS_BITVAR (sym->etype)  /* not a bit variable */
     )
-    {
+    {                                   
 
       /* we will use it after all optimizations
          and before liveRange calculation */
       sym->reqv = newiTempOperand (sym->type, 0);
       sym->reqv->key = sym->key;
+      OP_SYMBOL (sym->reqv)->prereqv = sym;
       OP_SYMBOL (sym->reqv)->key = sym->key;
       OP_SYMBOL (sym->reqv)->isreqv = 1;
       OP_SYMBOL (sym->reqv)->islocal = 1;
@@ -1532,10 +1660,13 @@ operandFromAst (ast * tree,int lvl)
 
     case EX_LINK:
       return operandFromLink (tree->opval.lnk);
-    }
+      break;
 
-  assert (0);
-  /*  Just to keep the comiler happy */
+    default:
+      assert (0);
+    }
+  
+  /*  Just to keep the compiler happy */
   return (operand *) 0;
 }
 
@@ -1571,10 +1702,11 @@ setOperandType (operand * op, sym_link * type)
     }
 
 }
+
 /*-----------------------------------------------------------------*/
 /* Get size in byte of ptr need to access an array                 */
 /*-----------------------------------------------------------------*/
-int
+static int
 getArraySizePtr (operand * op)
 {
   sym_link *ltype = operandType(op);
@@ -1612,7 +1744,8 @@ getArraySizePtr (operand * op)
 /*-----------------------------------------------------------------*/
 /* perform "usual unary conversions"                               */
 /*-----------------------------------------------------------------*/
-operand *
+#if 0
+static operand *
 usualUnaryConversions (operand * op)
 {
   if (IS_INTEGRAL (operandType (op)))
@@ -1625,22 +1758,94 @@ usualUnaryConversions (operand * op)
     }
   return op;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* perform "usual binary conversions"                              */
 /*-----------------------------------------------------------------*/
-sym_link *
-usualBinaryConversions (operand ** op1, operand ** op2)
+
+static sym_link *
+usualBinaryConversions (operand ** op1, operand ** op2,
+                        RESULT_TYPE resultType, char op)
 {
   sym_link *ctype;
   sym_link *rtype = operandType (*op2);
   sym_link *ltype = operandType (*op1);
+
+#define OLDONEBYTEOPS 1
+
+#ifdef OLDONEBYTEOPS  
+  bool oldOneByteOps = FALSE;
+  static bool saidHello = FALSE;
+  
+  if (strcmp (port->target, "pic14") == 0)
+    oldOneByteOps = TRUE;
+  if (getenv ("SDCC_NEWONEBYTEOPS"))
+    {
+      if (!saidHello)
+        {
+         fprintf (stderr, "Override: oldOneByteOps = FALSE\n");
+         saidHello = TRUE;
+       }
+      oldOneByteOps = FALSE;
+    }
+  else if (getenv ("SDCC_OLDONEBYTEOPS"))
+    {
+      if (!saidHello)
+        {
+          fprintf (stderr, "Override: oldOneByteOps = TRUE\n");
+         saidHello = TRUE;
+       }
+      oldOneByteOps = TRUE;
+    }
+
+
+  if (   oldOneByteOps
+      && (   (IS_CHAR (getSpec (ltype)) && !IS_UNSIGNED (getSpec (ltype)))
+         || (IS_CHAR (getSpec (rtype)) && !IS_UNSIGNED (getSpec (rtype)))))
+    /* one or two signed char operands: promote to int */
+    resultType = RESULT_TYPE_INT;
+#endif
   
-  ctype = computeType (ltype, rtype);
+  ctype = computeType (ltype, rtype, resultType, op);
+
+#ifdef OLDONEBYTEOPS
+
+  if (oldOneByteOps)
+    {
+      if (   op == '*'
+          && IS_CHAR (getSpec (ltype)) && IS_UNSIGNED (getSpec (ltype))
+         && IS_CHAR (getSpec (rtype)) && IS_UNSIGNED (getSpec (rtype)))
+         {
+           /* two unsigned char operands and Mult: no promotion */
+           return ctype;
+         }
+      *op1 = geniCodeCast (ctype, *op1, TRUE);
+      *op2 = geniCodeCast (ctype, *op2, TRUE);
+
+      return ctype;
+    }
+
+#endif
+
+  switch (op)
+    {
+      case '*':
+      case '/':
+      case '%':
+       if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
+         {
+           /* one byte operations: keep signedness for code generator */
+           return ctype;
+         }
+       break;
+      default:
+       break;
+    }
 
   *op1 = geniCodeCast (ctype, *op1, TRUE);
   *op2 = geniCodeCast (ctype, *op2, TRUE);
-  
+       
   return ctype;
 }
 
@@ -1669,7 +1874,7 @@ geniCodeRValue (operand * op, bool force)
   /* if this is not a temp symbol then */
   if (!IS_ITEMP (op) &&
       !force &&
-      !IN_FARSPACE (SPEC_OCLS (etype)))
+      !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
     {
       op = operandFromOperand (op);
       op->isaddr = 0;
@@ -1678,7 +1883,7 @@ geniCodeRValue (operand * op, bool force)
 
   if (IS_SPEC (type) &&
       IS_TRUE_SYMOP (op) &&
-      (!IN_FARSPACE (SPEC_OCLS (etype)) ||
+      (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
       (options.model == MODEL_FLAT24) ))
     {
       op = operandFromOperand (op);
@@ -1705,7 +1910,7 @@ geniCodeRValue (operand * op, bool force)
 /*-----------------------------------------------------------------*/
 /* geniCodeCast - changes the value from one type to another       */
 /*-----------------------------------------------------------------*/
-operand *
+static operand *
 geniCodeCast (sym_link * type, operand * op, bool implicit)
 {
   iCode *ic;
@@ -1721,22 +1926,30 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
       return op;
     }
 
+  if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
+    {
+      geniCodeArray2Ptr (op);
+      op->isaddr = 0;
+    }
+    
   /* if the operand is already the desired type then do nothing */
   if (compareType (type, optype) == 1)
     return op;
 
   /* if this is a literal then just change the type & return */
   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
-    return operandFromValue (valCastLiteral (type,
-                                            operandLitValue (op)));
+    {
+      return operandFromValue (valCastLiteral (type,
+                                              operandLitValue (op)));
+    }
 
   /* if casting to/from pointers, do some checking */
   if (IS_PTR(type)) { // to a pointer
     if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
-      if (IS_INTEGRAL(optype)) { 
-       // maybe this is NULL, than it's ok. 
+      if (IS_INTEGRAL(optype)) {
+       // maybe this is NULL, than it's ok.
        if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
-         if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
+         if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
            // no way to set the storage
            if (IS_LITERAL(optype)) {
              werror(E_LITERAL_GENERIC);
@@ -1750,19 +1963,19 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
            errors++;
          }
        }
-      }        else { 
+      }        else {
        // shouldn't do that with float, array or structure unless to void
-       if (!IS_VOID(getSpec(type)) && 
+       if (!IS_VOID(getSpec(type)) &&
            !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
          werror(E_INCOMPAT_TYPES);
          errors++;
        }
       }
     } else { // from a pointer to a pointer
-      if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
+      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 (implicit) { // if not to generic, they have to match
            if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
              werror(E_INCOMPAT_PTYPES);
              errors++;
@@ -1789,6 +2002,14 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
   }
 
   /* if they are the same size create an assignment */
+  
+  /* This seems very dangerous to me, since there are several */
+  /* optimizations (for example, gcse) that don't notice the  */
+  /* cast hidden in this assignement and may simplify an      */
+  /* iCode to use the original (uncasted) operand.            */
+  /* Unfortunately, other things break when this cast is      */
+  /* made explicit. Need to fix this someday.                 */
+  /* -- EEP, 2004/01/21                                       */
   if (getSize (type) == getSize (optype) &&
       !IS_BITFIELD (type) &&
       !IS_FLOAT (type) &&
@@ -1796,11 +2017,10 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
       ((IS_SPEC (type) && IS_SPEC (optype)) ||
        (!IS_SPEC (type) && !IS_SPEC (optype))))
     {
-
       ic = newiCode ('=', NULL, op);
       IC_RESULT (ic) = newiTempOperand (type, 0);
       SPIL_LOC (IC_RESULT (ic)) =
-       (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
+        (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
       IC_RESULT (ic)->isaddr = 0;
     }
   else
@@ -1825,7 +2045,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
 /*-----------------------------------------------------------------*/
 /* geniCodeLabel - will create a Label                             */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeLabel (symbol * label)
 {
   iCode *ic;
@@ -1837,7 +2057,7 @@ geniCodeLabel (symbol * label)
 /*-----------------------------------------------------------------*/
 /* geniCodeGoto  - will create a Goto                              */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeGoto (symbol * label)
 {
   iCode *ic;
@@ -1849,8 +2069,8 @@ geniCodeGoto (symbol * label)
 /*-----------------------------------------------------------------*/
 /* geniCodeMultiply - gen intermediate code for multiplication     */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeMultiply (operand * left, operand * right,int resultIsInt)
+static operand *
+geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   int p2 = 0;
@@ -1863,31 +2083,29 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt)
                                      right->operand.valOperand));
 
   if (IS_LITERAL(retype)) {
-    p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
+    p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
   }
 
-  resType = usualBinaryConversions (&left, &right);
+  resType = usualBinaryConversions (&left, &right, resultType, '*');
 #if 1
   rtype = operandType (right);
   retype = getSpec (rtype);
   ltype = operandType (left);
   letype = getSpec (ltype);
 #endif
-  if (resultIsInt)
-    {
-      SPEC_NOUN(getSpec(resType))=V_INT;
-    }
 
   /* if the right is a literal & power of 2 */
   /* then make it a left shift              */
-  /* code generated for 1 byte * 1 byte literal = 2 bytes result is more 
-     efficient in most cases than 2 bytes result = 2 bytes << literal 
+  /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
+     efficient in most cases than 2 bytes result = 2 bytes << literal
      if port has 1 byte muldiv */
-  if (p2 && !IS_FLOAT (letype) &&
-      !((resultIsInt) && (getSize (resType) != getSize (ltype)) && 
-       (port->support.muldiv == 1)))
+  if (p2 && !IS_FLOAT (letype)
+      && !((resultType != RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
+           && (port->support.muldiv == 1))
+      && strcmp (port->target, "pic14") != 0  /* don't shift for pic */
+      && strcmp (port->target, "pic16") != 0)
     {
-      if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
+      if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
        {
          /* LEFT_OP need same size for left and result, */
          left = geniCodeCast (resType, left, TRUE);
@@ -1912,8 +2130,8 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt)
 /*-----------------------------------------------------------------*/
 /* geniCodeDivision - gen intermediate code for division           */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeDivision (operand * left, operand * right)
+static operand *
+geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   int p2 = 0;
@@ -1923,15 +2141,15 @@ geniCodeDivision (operand * left, operand * right)
   sym_link *ltype = operandType (left);
   sym_link *letype = getSpec (ltype);
 
-  resType = usualBinaryConversions (&left, &right);
+  resType = usualBinaryConversions (&left, &right, resultType, '/');
 
-  /* if the right is a literal & power of 2 
-     and left is unsigned then make it a    
+  /* if the right is a literal & power of 2
+     and left is unsigned then make it a
      right shift */
   if (IS_LITERAL (retype) &&
       !IS_FLOAT (letype) &&
-      SPEC_USIGN(letype) &&
-      (p2 = powof2 ((unsigned long)
+      IS_UNSIGNED(letype) &&
+      (p2 = powof2 ((TYPE_UDWORD)
                    floatFromVal (right->operand.valOperand)))) {
     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
   }
@@ -1950,8 +2168,8 @@ geniCodeDivision (operand * left, operand * right)
 /*-----------------------------------------------------------------*/
 /* geniCodeModulus  - gen intermediate code for modulus            */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeModulus (operand * left, operand * right)
+static operand *
+geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   sym_link *resType;
@@ -1962,7 +2180,7 @@ geniCodeModulus (operand * left, operand * right)
     return operandFromValue (valMod (left->operand.valOperand,
                                     right->operand.valOperand));
 
-  resType = usualBinaryConversions (&left, &right);
+  resType = usualBinaryConversions (&left, &right, resultType, '%');
 
   /* now they are the same size */
   ic = newiCode ('%', left, right);
@@ -2003,17 +2221,18 @@ 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)));
+                          operandFromLit (getSize (ltype->next)),
+                          FALSE);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSubtract - generates code for subtraction               */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeSubtract (operand * left, operand * right)
+static operand *
+geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   int isarray = 0;
@@ -2036,12 +2255,15 @@ geniCodeSubtract (operand * left, operand * right)
     {
       isarray = left->isaddr;
       right = geniCodeMultiply (right,
-                               operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+                               operandFromLit (getSize (ltype->next)),
+                               (getArraySizePtr(left) >= INTSIZE) ?
+                                 RESULT_TYPE_INT :
+                                 RESULT_TYPE_CHAR);
       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
     }
   else
     {                          /* make them the same size */
-      resType = usualBinaryConversions (&left, &right);
+      resType = usualBinaryConversions (&left, &right, resultType, '-');
     }
 
   ic = newiCode ('-', left, right);
@@ -2060,28 +2282,23 @@ geniCodeSubtract (operand * left, operand * right)
 /*-----------------------------------------------------------------*/
 /* geniCodeAdd - generates iCode for addition                      */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeAdd (operand * left, operand * right, int lvl)
+static operand *
+geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
 {
   iCode *ic;
   sym_link *resType;
   operand *size;
   int isarray = 0;
+  bool indexUnsigned;
   LRTYPE;
 
-#if 0
-  /* if left is an array then array access */
-  if (IS_ARRAY (ltype))
-    return geniCodeArray (left, right,lvl);
-#endif
-
   /* if the right side is LITERAL zero */
   /* return the left side              */
-  if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
+  if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
     return left;
 
   /* if left is literal zero return right */
-  if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
+  if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
     return right;
 
   /* if left is a pointer then size */
@@ -2089,22 +2306,34 @@ geniCodeAdd (operand * left, operand * right, int lvl)
     {
       isarray = left->isaddr;
       // 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));
-      }
+      if (getSize (ltype->next) != 1)
+        {
+         size  = operandFromLit (getSize (ltype->next));
+         SPEC_USIGN (getSpec (operandType (size))) = 1;
+         indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
+         right = geniCodeMultiply (right,
+                                   size,
+                                   (getArraySizePtr(left) >= INTSIZE) ?
+                                     RESULT_TYPE_INT :
+                                     RESULT_TYPE_CHAR);
+         /* Even if right is a 'unsigned char',
+            the result will be a 'signed int' due to the promotion rules.
+            It doesn't make sense when accessing arrays, so let's fix it here: */
+         if (indexUnsigned)
+           SPEC_USIGN (getSpec (operandType (right))) = 1;
+       }
       resType = copyLinkChain (ltype);
     }
   else
     { // make them the same size
-      resType = usualBinaryConversions (&left, &right);
+      resType = usualBinaryConversions (&left, &right, resultType, '+');
     }
 
   /* if they are both literals then we know */
   if (IS_LITERAL (letype) && IS_LITERAL (retype)
       && left->isLiteral && right->isLiteral)
-    return operandFromValue (valPlus (valFromType (letype),
-                                     valFromType (retype)));
+    return operandFromValue (valPlus (valFromType (ltype),
+                                     valFromType (rtype)));
 
   ic = newiCode ('+', left, right);
 
@@ -2131,51 +2360,31 @@ aggrToPtr (sym_link * type, bool force)
   sym_link *etype;
   sym_link *ptype;
 
-
   if (IS_PTR (type) && !force)
     return type;
 
   etype = getSpec (type);
-  ptype = newLink ();
+  ptype = newLink (DECLARATOR);
 
   ptype->next = type;
-  /* if the output class is generic */
-  if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
-    DCL_PTR_CONST (ptype) = port->mem.code_ro;
-
-  /* if the variable was declared a constant */
-  /* then the pointer points to a constant */
-  if (IS_CONSTANT (etype))
-    DCL_PTR_CONST (ptype) = 1;
-
-  /* the variable was volatile then pointer to volatile */
-  if (IS_VOLATILE (etype))
-    DCL_PTR_VOLATILE (ptype) = 1;
+
+  /* set the pointer depending on the storage class */
+  DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
   return ptype;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeArray2Ptr - array to pointer                            */
 /*-----------------------------------------------------------------*/
-operand *
+static operand *
 geniCodeArray2Ptr (operand * op)
 {
   sym_link *optype = operandType (op);
   sym_link *opetype = getSpec (optype);
 
   /* set the pointer depending on the storage class */
-  if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
-    DCL_PTR_CONST (optype) = port->mem.code_ro;
-
+  DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
 
-  /* if the variable was declared a constant */
-  /* then the pointer points to a constant */
-  if (IS_CONSTANT (opetype))
-    DCL_PTR_CONST (optype) = 1;
-
-  /* the variable was volatile then pointer to volatile */
-  if (IS_VOLATILE (opetype))
-    DCL_PTR_VOLATILE (optype) = 1;
   op->isaddr = 0;
   return op;
 }
@@ -2184,11 +2393,13 @@ geniCodeArray2Ptr (operand * op)
 /*-----------------------------------------------------------------*/
 /* geniCodeArray - array access                                    */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeArray (operand * left, operand * right,int lvl)
+static operand *
+geniCodeArray (operand * left, operand * right, int lvl)
 {
   iCode *ic;
+  operand *size;
   sym_link *ltype = operandType (left);
+  bool indexUnsigned;
 
   if (IS_PTR (ltype))
     {
@@ -2196,21 +2407,39 @@ geniCodeArray (operand * left, operand * right,int lvl)
        {
          left = geniCodeRValue (left, FALSE);
        }
-      return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
-    }
 
+      return geniCodeDerefPtr (geniCodeAdd (left,
+                                           right,
+                                           (getArraySizePtr(left) >= INTSIZE) ?
+                                             RESULT_TYPE_INT :
+                                             RESULT_TYPE_CHAR,
+                                           lvl),
+                              lvl);
+    }
+  size = operandFromLit (getSize (ltype->next));
+  SPEC_USIGN (getSpec (operandType (size))) = 1;
+  indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
   right = geniCodeMultiply (right,
-                           operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
-
+                           size,
+                           (getArraySizePtr(left) >= INTSIZE) ?
+                             RESULT_TYPE_INT :
+                             RESULT_TYPE_CHAR);
+  /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
+     It doesn't make sense when accessing arrays, so let's fix it here: */
+  if (indexUnsigned)
+    SPEC_USIGN (getSpec (operandType (right))) = 1;
   /* we can check for limits here */
+  /* already done in SDCCast.c
   if (isOperandLiteral (right) &&
       IS_ARRAY (ltype) &&
       DCL_ELEM (ltype) &&
       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
     {
-      werror (E_ARRAY_BOUND);
-      right = operandFromLit (0);
+      werror (W_IDX_OUT_OF_BOUNDS,
+             (int) operandLitValue (right) / getSize (ltype->next),
+             DCL_ELEM (ltype));
     }
+  */
 
   ic = newiCode ('+', left, right);
 
@@ -2221,11 +2450,12 @@ geniCodeArray (operand * left, operand * right,int lvl)
 
   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
   ADDTOCHAIN (ic);
+
   return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* geniCodeStruct - generates intermediate code for structres      */
+/* geniCodeStruct - generates intermediate code for structures     */
 /*-----------------------------------------------------------------*/
 operand *
 geniCodeStruct (operand * left, operand * right, bool islval)
@@ -2237,6 +2467,8 @@ geniCodeStruct (operand * left, operand * right, bool islval)
   symbol *element = getStructElement (SPEC_STRUCT (etype),
                                      right->operand.symOperand);
 
+  wassert(IS_SYMOP(right));
+    
   /* add the offset */
   ic = newiCode ('+', left, operandFromLit (element->offset));
 
@@ -2248,13 +2480,13 @@ geniCodeStruct (operand * left, operand * right, bool islval)
   SPEC_SCLS (retype) = SPEC_SCLS (etype);
   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);
   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
 }
@@ -2309,7 +2541,7 @@ geniCodePostInc (operand * op)
 /* geniCodePreInc - generate code for preIncrement                 */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodePreInc (operand * op)
+geniCodePreInc (operand * op, bool lvalue)
 {
   iCode *ic;
   sym_link *optype = operandType (op);
@@ -2335,8 +2567,11 @@ geniCodePreInc (operand * op)
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-
-  return geniCodeAssign (op, result, 0);
+  (void) geniCodeAssign (op, result, 0);
+  if (lvalue || IS_TRUE_SYMOP (op))
+    return op;
+  else
+    return result;
 }
 
 /*-----------------------------------------------------------------*/
@@ -2389,7 +2624,7 @@ geniCodePostDec (operand * op)
 /* geniCodePreDec - generate code for pre  decrement               */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodePreDec (operand * op)
+geniCodePreDec (operand * op, bool lvalue)
 {
   iCode *ic;
   sym_link *optype = operandType (op);
@@ -2415,8 +2650,11 @@ geniCodePreDec (operand * op)
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-
-  return geniCodeAssign (op, result, 0);
+  (void) geniCodeAssign (op, result, 0);
+  if (lvalue || IS_TRUE_SYMOP (op))
+    return op;
+  else
+    return result;
 }
 
 
@@ -2450,6 +2688,13 @@ geniCodeAddressOf (operand * op)
   sym_link *optype = operandType (op);
   sym_link *opetype = getSpec (optype);
 
+  if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
+    {
+      op = operandFromOperand (op);
+      op->isaddr = 0;
+      return op;
+    }
+  
   /* lvalue check already done in decorateType */
   /* this must be a lvalue */
 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
@@ -2457,19 +2702,10 @@ geniCodeAddressOf (operand * op)
 /*  return op; */
 /*     } */
 
-  p = newLink ();
-  p->class = DECLARATOR;
+  p = newLink (DECLARATOR);
 
   /* set the pointer depending on the storage class */
-  if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
-    DCL_PTR_CONST (p) = port->mem.code_ro;
-
-  /* make sure we preserve the const & volatile */
-  if (IS_CONSTANT (opetype))
-    DCL_PTR_CONST (p) = 1;
-
-  if (IS_VOLATILE (opetype))
-    DCL_PTR_VOLATILE (p) = 1;
+  DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
 
   p->next = copyLinkChain (optype);
 
@@ -2539,16 +2775,19 @@ geniCodeDerefPtr (operand * op,int lvl)
   sym_link *rtype, *retype;
   sym_link *optype = operandType (op);
 
-  /* if this is a pointer then generate the rvalue */
-  if (IS_PTR (optype))
+  // if this is an array then array access
+  if (IS_ARRAY (optype)) {
+    // don't worry, this will be optimized out later
+    return geniCodeArray (op, operandFromLit (0), lvl);
+  }
+
+  // just in case someone screws up
+  wassert (IS_PTR (optype));
+
+  if (IS_TRUE_SYMOP (op))
     {
-      if (IS_TRUE_SYMOP (op))
-       {
-         op->isaddr = 1;
-         op = geniCodeRValue (op, TRUE);
-       }
-      else
-       op = geniCodeRValue (op, TRUE);
+      op->isaddr = 1;
+      op = geniCodeRValue (op, TRUE);
     }
 
   /* now get rid of the pointer part */
@@ -2559,19 +2798,12 @@ geniCodeDerefPtr (operand * op,int lvl)
   else
     {
       retype = getSpec (rtype = copyLinkChain (optype->next));
+      /* outputclass needs 2b updated */
+      setOClass (optype, retype);
     }
-
-  /* if this is a pointer then outputclass needs 2b updated */
-  if (IS_PTR (optype))
-    setOClass (optype, retype);
-
+  
   op->isGptr = IS_GENPTR (optype);
 
-  /* if the pointer was declared as a constant */
-  /* then we cannot allow assignment to the derefed */
-  if (IS_PTR_CONST (optype))
-    SPEC_CONST (retype) = 1;
-
   op->isaddr = (IS_PTR (rtype) ||
                IS_STRUCT (rtype) ||
                IS_INT (rtype) ||
@@ -2647,11 +2879,54 @@ geniCodeLogic (operand * left, operand * right, int op)
      check if the literal value is within bounds */
   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
     {
-      checkConstantRange(ltype, 
+      checkConstantRange(ltype,
                         OP_VALUE(right), "compare operation", 1);
     }
 
-  ctype = usualBinaryConversions (&left, &right);
+  /* if one operand is a pointer and the other is a literal generic void pointer,
+     change the type of the literal generic void pointer to match the other pointer */
+  if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
+      && IS_PTR (rtype) && !IS_GENPTR(rtype))
+    {
+      /* find left's definition */
+      ic = (iCode *) setFirstItem (iCodeChain);
+      while (ic)
+        {
+          if (((ic->op == CAST) || (ic->op == '='))
+              && isOperandEqual(left, IC_RESULT (ic)))
+            break;
+          else
+            ic = setNextItem (iCodeChain);
+        }
+      /* if casting literal to generic pointer, then cast to rtype instead */
+      if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
+        {
+          left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
+          ltype = operandType(left);
+        }
+    }
+  if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
+      && IS_PTR (ltype) && !IS_GENPTR(ltype))
+    {
+      /* find right's definition */
+      ic = (iCode *) setFirstItem (iCodeChain);
+      while (ic)
+        {
+          if (((ic->op == CAST) || (ic->op == '='))
+              && isOperandEqual(right, IC_RESULT (ic)))
+            break;
+          else
+            ic = setNextItem (iCodeChain);
+        }
+      /* if casting literal to generic pointer, then cast to rtype instead */
+      if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
+        {
+          right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
+          rtype = operandType(right);
+        }
+    }
+
+  ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, ' ');
 
   ic = newiCode (op, left, right);
   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
@@ -2759,11 +3034,12 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   else if (compareType (ltype, rtype) < 0)
     right = geniCodeCast (ltype, right, TRUE);
 
-  /* if left is a true symbol & ! volatile
+  /* If left is a true symbol & ! volatile
      create an assignment to temporary for
      the right & then assign this temporary
-     to the symbol this is SSA . isn't it simple
-     and folks have published mountains of paper on it */
+     to the symbol. This is SSA (static single
+     assignment). Isn't it simple and folks have
+     published mountains of paper on it */
   if (IS_TRUE_SYMOP (left) &&
       !isOperandVolatile (left, FALSE) &&
       isOperandGlobal (left))
@@ -2791,6 +3067,24 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   return left;
 }
 
+/*-----------------------------------------------------------------*/
+/* geniCodeDummyRead - generate code for dummy read                */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeDummyRead (operand * op)
+{
+  iCode *ic;
+  sym_link *type = operandType (op);
+
+  if (!IS_VOLATILE(type))
+    return;
+    
+  ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
+  ADDTOCHAIN (ic);
+
+  ic->nosupdate = 1;
+}
+
 /*-----------------------------------------------------------------*/
 /* geniCodeSEParms - generate code for side effecting fcalls       */
 /*-----------------------------------------------------------------*/
@@ -2830,7 +3124,7 @@ geniCodeSEParms (ast * parms,int lvl)
 /*-----------------------------------------------------------------*/
 value *
 geniCodeParms (ast * parms, value *argVals, int *stack, 
-              sym_link * fetype, symbol * func,int lvl)
+              sym_link * ftype, int lvl)
 {
   iCode *ic;
   operand *pval;
@@ -2840,14 +3134,14 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
 
   if (argVals==NULL) {
     // first argument
-    argVals=FUNC_ARGS(func->type);
+    argVals = FUNC_ARGS (ftype);
   }
 
   /* if this is a param node then do the left & right */
   if (parms->type == EX_OP && parms->opval.op == PARAM)
     {
-      argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
-      argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
+      argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
+      argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
       return argVals;
     }
 
@@ -2871,24 +3165,24 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
     }
 
   /* if register parm then make it a send */
-  if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
-      IFFUNC_ISBUILTIN(func->type))
+  if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
+      IFFUNC_ISBUILTIN(ftype))
     {
       ic = newiCode (SEND, pval, NULL);
       ic->argreg = SPEC_ARGREG(parms->etype);
-      ic->builtinSEND = FUNC_ISBUILTIN(func->type);
+      ic->builtinSEND = FUNC_ISBUILTIN(ftype);
       ADDTOCHAIN (ic);
     }
   else
     {
       /* now decide whether to push or assign */
-      if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
+      if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
        {
 
          /* assign */
          operand *top = operandFromSymbol (argVals->sym);
          /* clear useDef and other bitVectors */
-         OP_USES_SET ((top), OP_DEFS_SET ((top), OP_SYMBOL(top)->clashes = NULL));
+         OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
          geniCodeAssign (top, pval, 1);
        }
       else
@@ -2916,12 +3210,13 @@ geniCodeCall (operand * left, ast * parms,int lvl)
   iCode *ic;
   operand *result;
   sym_link *type, *etype;
+  sym_link *ftype;
   int stack = 0;
 
   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
     werror (E_FUNCTION_EXPECTED);
-    return NULL;
+    return operandFromValue(valueFromLit(0));
   }
 
   /* take care of parameters with side-effecting
@@ -2929,8 +3224,12 @@ geniCodeCall (operand * left, ast * parms,int lvl)
      of overlaying function parameters */
   geniCodeSEParms (parms,lvl);
 
+  ftype = operandType (left);
+  if (IS_CODEPTR (ftype))
+    ftype = ftype->next;
+    
   /* first the parameters */
-  geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
+  geniCodeParms (parms, NULL, &stack, ftype, lvl);
 
   /* now call : if symbol then pcall */
   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
@@ -2939,7 +3238,7 @@ geniCodeCall (operand * left, ast * parms,int lvl)
     ic = newiCode (CALL, left, NULL);
   }
 
-  type = copyLinkChain (operandType (left)->next);
+  type = copyLinkChain (ftype->next);
   etype = getSpec (type);
   SPEC_EXTR (etype) = 0;
   IC_RESULT (ic) = result = newiTempOperand (type, 1);
@@ -2974,7 +3273,7 @@ geniCodeReceive (value * args)
          if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
            {
 
-             if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+             if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
                  options.stackAuto == 0 &&
                  (!(options.model == MODEL_FLAT24)) )
                {
@@ -3140,6 +3439,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   operand *boundary;
   symbol *falseLabel;
   set *labels = NULL;
+  int needRangeCheck = !optimize.noJTabBoundary
+                       || tree->values.switchVals.swDefault;
 
   if (!tree || !caseVals)
     return 0;
@@ -3148,7 +3449,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* all integer numbers between the maximum & minimum must */
   /* be present , the maximum value should not exceed 255 */
   min = max = (int) floatFromVal (vch = caseVals);
-  sprintf (buffer, "_case_%d_%d",
+  SNPRINTF (buffer, sizeof(buffer), 
+           "_case_%d_%d",
           tree->values.switchVals.swNum,
           min);
   addSet (&labels, newiTempLabel (buffer));
@@ -3161,7 +3463,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
     {
       if (((t = (int) floatFromVal (vch)) - max) != 1)
        return 0;
-      sprintf (buffer, "_case_%d_%d",
+      SNPRINTF (buffer, sizeof(buffer), 
+               "_case_%d_%d",
               tree->values.switchVals.swNum,
               t);
       addSet (&labels, newiTempLabel (buffer));
@@ -3173,25 +3476,30 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* 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 ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
+  if ((needRangeCheck && cnt <= 2) || max > (255 / 3))
     return 0;
 
   if (tree->values.switchVals.swDefault)
-    sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+    }
   else
-    sprintf (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 */
   /* first we rule out the boundary conditions */
   /* if only optimization says so */
-  if (!optimize.noJTabBoundary)
+  if (needRangeCheck)
     {
       sym_link *cetype = getSpec (operandType (cond));
       /* no need to check the lower bound if
          the condition is unsigned & minimum value is zero */
-      if (!(min == 0 && SPEC_USIGN (cetype)))
+      if (!(min == 0 && IS_UNSIGNED (cetype)))
        {
          boundary = geniCodeLogic (cond, operandFromLit (min), '<');
          ic = newiCodeCondition (boundary, falseLabel, NULL);
@@ -3207,8 +3515,9 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* if the min is not zero then we no make it zero */
   if (min)
     {
-      cond = geniCodeSubtract (cond, operandFromLit (min));
-      setOperandType (cond, UCHARTYPE);
+      cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
+      if (!IS_LITERAL(getSpec(operandType(cond))))
+        setOperandType (cond, UCHARTYPE);
     }
 
   /* now create the jumptable */
@@ -3222,13 +3531,36 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
 /*-----------------------------------------------------------------*/
 /* geniCodeSwitch - changes a switch to a if statement             */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeSwitch (ast * tree,int lvl)
 {
   iCode *ic;
   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)
+        {
+          caseVal = (int) floatFromVal (caseVals);
+          if (caseVal == switchVal)
+            {
+              SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
+                       tree->values.switchVals.swNum, caseVal);
+              trueLabel = newiTempLabel (buffer);
+              geniCodeGoto (trueLabel);
+              goto jumpTable;
+            }
+          caseVals = caseVals->next;
+        }
+      goto defaultOrBreak;
+    }
 
   /* if we can make this a jump table */
   if (geniCodeJumpTable (cond, caseVals, tree))
@@ -3242,7 +3574,7 @@ geniCodeSwitch (ast * tree,int lvl)
                                        operandFromValue (caseVals),
                                        EQ_OP);
 
-      sprintf (buffer, "_case_%d_%d",
+      SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
               tree->values.switchVals.swNum,
               (int) floatFromVal (caseVals));
       trueLabel = newiTempLabel (buffer);
@@ -3253,12 +3585,16 @@ geniCodeSwitch (ast * tree,int lvl)
     }
 
 
-
+defaultOrBreak:
   /* if default is present then goto break else break */
   if (tree->values.switchVals.swDefault)
-    sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+    }
   else
-    sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+    }
 
   falseLabel = newiTempLabel (buffer);
   geniCodeGoto (falseLabel);
@@ -3283,7 +3619,7 @@ geniCodeInline (ast * tree)
 /*-----------------------------------------------------------------*/
 /* geniCodeArrayInit - intermediate code for array initializer     */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeArrayInit (ast * tree, operand *array)
 {
   iCode *ic;
@@ -3300,6 +3636,34 @@ geniCodeArrayInit (ast * tree, operand *array)
   }
   ADDTOCHAIN (ic);
 }
+       
+/*-----------------------------------------------------------------*/
+/* geniCodeCritical - intermediate code for a critical statement   */
+/*-----------------------------------------------------------------*/
+static void 
+geniCodeCritical (ast *tree, int lvl)
+{
+  iCode *ic;
+  operand *op = NULL;
+
+  /* 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 */
+  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);
+}
 
 /*-----------------------------------------------------------------*/
 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
@@ -3383,6 +3747,8 @@ ast2iCode (ast * tree,int lvl)
     block = tree->block;
   if (tree->level)
     scopeLevel = tree->level;
+  if (tree->seqPoint)
+    seqPoint = tree->seqPoint;
 
   if (tree->type == EX_VALUE)
     return operandFromValue (tree->opval.val);
@@ -3395,8 +3761,14 @@ ast2iCode (ast * tree,int lvl)
      (tree->opval.op == NULLOP ||
      tree->opval.op == BLOCK))
     {
-      ast2iCode (tree->left,lvl+1);
-      ast2iCode (tree->right,lvl+1);
+      if (tree->left && tree->left->type == EX_VALUE)
+        geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+      else
+        ast2iCode (tree->left,lvl+1);
+      if (tree->right && tree->right->type == EX_VALUE)
+        geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
+      else
+        ast2iCode (tree->right,lvl+1);
       return NULL;
     }
 
@@ -3409,7 +3781,8 @@ ast2iCode (ast * tree,int lvl)
       tree->opval.op != GOTO &&
       tree->opval.op != SWITCH &&
       tree->opval.op != FUNCTION &&
-      tree->opval.op != INLINEASM)
+      tree->opval.op != INLINEASM &&
+      tree->opval.op != CRITICAL)
     {
 
         if (IS_ASSIGN_OP (tree->opval.op) ||
@@ -3482,13 +3855,13 @@ ast2iCode (ast * tree,int lvl)
       if (left)
        return geniCodePostInc (left);
       else
-       return geniCodePreInc (right);
+       return geniCodePreInc (right, tree->lvalue);
 
     case DEC_OP:               /* decrement operator */
       if (left)
        return geniCodePostDec (left);
       else
-       return geniCodePreDec (right);
+       return geniCodePreDec (right, tree->lvalue);
 
     case '&':                  /* bitwise and or address of operator */
       if (right)
@@ -3509,29 +3882,35 @@ ast2iCode (ast * tree,int lvl)
 
     case '/':
       return geniCodeDivision (geniCodeRValue (left, FALSE),
-                              geniCodeRValue (right, FALSE));
+                              geniCodeRValue (right, FALSE),
+                              getResultTypeFromType (tree->ftype));
 
     case '%':
       return geniCodeModulus (geniCodeRValue (left, FALSE),
-                             geniCodeRValue (right, FALSE));
+                             geniCodeRValue (right, FALSE),
+                             getResultTypeFromType (tree->ftype));
     case '*':
       if (right)
        return geniCodeMultiply (geniCodeRValue (left, FALSE),
-                                geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
+                                geniCodeRValue (right, FALSE),
+                                getResultTypeFromType (tree->ftype));
       else
        return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
     case '-':
       if (right)
        return geniCodeSubtract (geniCodeRValue (left, FALSE),
-                                geniCodeRValue (right, FALSE));
+                                geniCodeRValue (right, FALSE),
+                                getResultTypeFromType (tree->ftype));
       else
        return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
 
     case '+':
       if (right)
        return geniCodeAdd (geniCodeRValue (left, FALSE),
-                           geniCodeRValue (right, FALSE),lvl);
+                           geniCodeRValue (right, FALSE),
+                           getResultTypeFromType (tree->ftype),
+                           lvl);
       else
        return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
 
@@ -3543,15 +3922,32 @@ ast2iCode (ast * tree,int lvl)
       return geniCodeRightShift (geniCodeRValue (left, FALSE),
                                 geniCodeRValue (right, FALSE));
     case CAST:
+#if 0 // this indeed needs a second thought
+      {
+       operand *op;
+
+       // let's keep this simple: get the rvalue we need
+       op=geniCodeRValue (right, FALSE);
+       // now cast it to whatever we want
+       op=geniCodeCast (operandType(left), op, FALSE);
+       // if this is going to be used as an lvalue, make it so
+       if (tree->lvalue) {
+         op->isaddr=1;
+       }
+       return op;
+      }
+#else // bug #604575, is it a bug ????
       return geniCodeCast (operandType (left),
                           geniCodeRValue (right, FALSE), FALSE);
+#endif
 
     case '~':
-    case '!':
     case RRC:
     case RLC:
+    case SWAP:
       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
 
+    case '!':
     case GETHBIT:
       {
        operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
@@ -3566,9 +3962,21 @@ ast2iCode (ast * tree,int lvl)
     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.
       return geniCodeLogic (geniCodeRValue (left, FALSE),
-                           geniCodeRValue (right, FALSE),
-                           tree->opval.op);
+                            geniCodeRValue (right, FALSE),
+                            tree->opval.op);
+      */
+      {
+       operand *leftOp, *rightOp;
+
+       rightOp = geniCodeRValue (right, FALSE);
+       leftOp  = geniCodeRValue (left , FALSE);
+
+       return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+      }
     case '?':
       return geniCodeConditional (tree,lvl);
 
@@ -3593,20 +4001,25 @@ ast2iCode (ast * tree,int lvl)
        geniCodeAssign (left,
                geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE),FALSE), 0);
+                                 geniCodeRValue (right, FALSE), FALSE),
+                                 getResultTypeFromType (tree->ftype));
 
     case DIV_ASSIGN:
       return
        geniCodeAssign (left,
                geniCodeDivision (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype)),
+                       0);
     case MOD_ASSIGN:
       return
        geniCodeAssign (left,
                 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype)),
+                       0);
     case ADD_ASSIGN:
       {
        sym_link *rtype = operandType (right);
@@ -3621,7 +4034,10 @@ ast2iCode (ast * tree,int lvl)
        return geniCodeAssign (left,
                     geniCodeAdd (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 right,lvl), 0);
+                                 right,
+                                 getResultTypeFromType (tree->ftype),
+                                 lvl),
+                              0);
       }
     case SUB_ASSIGN:
       {
@@ -3640,7 +4056,9 @@ ast2iCode (ast * tree,int lvl)
          geniCodeAssign (left,
                geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 right), 0);
+                                 right,
+                                 getResultTypeFromType (tree->ftype)),
+                         0);
       }
     case LEFT_ASSIGN:
       return
@@ -3715,6 +4133,9 @@ ast2iCode (ast * tree,int lvl)
     case ARRAYINIT:
        geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
        return NULL;
+    
+    case CRITICAL:
+       geniCodeCritical (tree, lvl);
     }
 
   return NULL;
@@ -3752,3 +4173,35 @@ iCodeFromAst (ast * tree)
   ast2iCode (tree,0);
   return reverseiCChain ();
 }
+
+static const char *opTypeToStr(OPTYPE op)
+{
+    switch(op)
+    {
+      case SYMBOL: return "symbol";
+      case VALUE: return "value";
+      case TYPE: return "type";
+    }
+    return "undefined type";    
+}
+
+
+operand *validateOpType(operand        *op, 
+                       const char      *macro,
+                       const char      *args,
+                       OPTYPE          type,
+                       const char      *file, 
+                       unsigned        line)
+{    
+    if (op && op->type == type)
+    {
+       return op;
+    }
+    fprintf(stderr, 
+           "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
+           " expected %s, got %s\n",
+           macro, args, file, line, 
+           opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
+    exit(-1);
+    return op; // never reached, makes compiler happy.
+}