Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / src / SDCCicode.c
index 36a4837e9c89a5b7b2c4b0eb77fea7bfaebada77..fe437728ce97f42e0c4663a2e65b8a25a3f8b5df 100644 (file)
@@ -25,6 +25,7 @@
 #include "common.h"
 #include "newalloc.h"
 #include "math.h"
+#include "dbuf_string.h"
 
 /*-----------------------------------------------------------------*/
 /* global variables       */
@@ -34,25 +35,27 @@ int iTempNum = 0;
 int iTempLblNum = 0;
 int operandKey = 0;
 int iCodeKey = 0;
-char *filename;
-int lineno;
+char *filename;                 /* current file name */
+int lineno = 1;                 /* current line number */
 int block;
 int scopeLevel;
+int seqPoint;
 
-symbol *returnLabel;           /* function return label */
-symbol *entryLabel;            /* function entry  label */
+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 *);
+operand *geniCodeAssign (operand *, operand *, int, int);
+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)
+#define PRINTFUNC(x) void x (struct dbuf_s *dbuf, iCode *ic, char *s)
 /* forward definition of ic print functions */
 PRINTFUNC (picGetValueAtAddr);
 PRINTFUNC (picSetValueAtAddr);
@@ -68,6 +71,8 @@ PRINTFUNC (picJumpTable);
 PRINTFUNC (picInline);
 PRINTFUNC (picReceive);
 PRINTFUNC (picDummyRead);
+PRINTFUNC (picCritical);
+PRINTFUNC (picEndCritical);
 
 iCodeTable codeTable[] =
 {
@@ -76,6 +81,9 @@ iCodeTable codeTable[] =
   {RRC, "rrc", picGenericOne, NULL},
   {RLC, "rlc", picGenericOne, NULL},
   {GETHBIT, "ghbit", picGenericOne, NULL},
+  {GETABIT, "gabit", picGenericOne, NULL},
+  {GETBYTE, "gbyte", picGenericOne, NULL},
+  {GETWORD, "gword", picGenericOne, NULL},
   {UNARYMINUS, "-", picGenericOne, NULL},
   {IPUSH, "push", picGenericOne, NULL},
   {IPOP, "pop", picGenericOne, NULL},
@@ -114,187 +122,162 @@ iCodeTable codeTable[] =
   {RECEIVE, "recv", picReceive, NULL},
   {SEND, "send", picGenericOne, NULL},
   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
-  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}
+  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
+  {CRITICAL, "critical_start", picCritical, NULL},
+  {ENDCRITICAL, "critical_end", picEndCritical, NULL},
+  {SWAP, "swap", picGenericOne, NULL}
 };
 
 /*-----------------------------------------------------------------*/
-/* checkConstantRange: check a constant against the type           */
+/* operandName - returns the name of the operand                   */
 /*-----------------------------------------------------------------*/
+int
+printOperand (operand * op, FILE * file)
+{
+  struct dbuf_s dbuf;
+  int ret;
+  int pnl = 0;
 
-
-/*   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)
-     pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
-     pedantic>1: "char c=200" is not allowed (evaluates to -56)
-*/
-
-void checkConstantRange(sym_link *ltype, value *val, char *msg,
-                       int pedantic) {
-  double max;
-  int warnings=0;
-  int negative=0;
-  long v;
-
-  max = pow ((double)2.0, (double)bitsForType(ltype));
-
-  if (SPEC_LONG(val->type)) {
-    if (SPEC_USIGN(val->type)) {
-      v=SPEC_CVAL(val->type).v_ulong;
-    } else {
-      v=SPEC_CVAL(val->type).v_long;
-    }
-  } else {
-    if (SPEC_USIGN(val->type)) {
-      v=SPEC_CVAL(val->type).v_uint;
-    } else {
-      v=SPEC_CVAL(val->type).v_int;
-    }
-  }
-
-
-#if 0
-  // this could be a good idea
-  if (options.pedantic)
-    pedantic=2;
-#endif
-
-  if (SPEC_NOUN(ltype)==FLOAT) {
-    // anything will do
-    return;
-  }
-
-  if (!SPEC_USIGN(val->type) && v<0) {
-    negative=1;
-    if (SPEC_USIGN(ltype) && (pedantic>1)) {
-      warnings++;
+  if (!file)
+    {
+      file = stdout;
+      pnl = 1;
     }
-    v=-v;
-  }
-
-  // if very pedantic: "char c=200" is not allowed
-  if (pedantic>1 && !SPEC_USIGN(ltype)) {
-    max = max/2 + negative;
-  }
-
-  if (v >= max) {
-    warnings++;
-  }
+  dbuf_init (&dbuf, 1024);
+  ret = dbuf_printOperand(op, &dbuf);
+  dbuf_write_and_destroy (&dbuf, file);
 
-#if 0 // temporary disabled, leaving the warning as a reminder
-  if (warnings) {
-    SNPRINTF (message, sizeof(message), "for %s %s in %s", 
-            SPEC_USIGN(ltype) ? "unsigned" : "signed",
-            nounName(ltype), msg);
-    werror (W_CONST_RANGE, message);
+  if (pnl)
+    putc ('\n', file);
 
-    if (pedantic>1)
-      fatalError++;
-  }
-#endif
+  return ret;
 }
 
-/*-----------------------------------------------------------------*/
-/* operandName - returns the name of the operand                   */
-/*-----------------------------------------------------------------*/
-int 
-printOperand (operand * op, FILE * file)
+int
+dbuf_printOperand (operand * op, struct dbuf_s *dbuf)
 {
   sym_link *opetype;
-  int pnl = 0;
 
   if (!op)
     return 1;
 
-  if (!file)
-    {
-      file = stdout;
-      pnl = 1;
-    }
   switch (op->type)
     {
 
     case VALUE:
       opetype = getSpec (operandType (op));
-      if (SPEC_NOUN (opetype) == V_FLOAT)
-       fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
+      if (IS_FLOAT (opetype))
+        dbuf_printf (dbuf, "%g {", SPEC_CVAL (opetype).v_float);
+      else if (IS_FIXED16X16 (opetype))
+        dbuf_printf (dbuf, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16));
       else
-       fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
-      printTypeChain (operandType (op), file);
-      fprintf (file, "}");
+        dbuf_printf (dbuf, "0x%x {", (unsigned int) ulFromVal (op->operand.valOperand));
+      dbuf_printTypeChain (operandType (op), dbuf);
+      dbuf_append_char (dbuf, '}');
       break;
 
     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}"  , */
-              (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_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
-              OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
-       );
+//#if REGA      /* { */
+    if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
+      dbuf_printf (dbuf, "%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->aggr2ptr, OP_SYMBOL (op)->isreqv,
+               OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
+               OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
+        );
       {
-       fprintf (file, "{");
-       printTypeChain (operandType (op), file);
-       if (SPIL_LOC (op) && IS_ITEMP (op))
-         fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
-       fprintf (file, "}");
+        dbuf_append_char (dbuf, '{');
+        dbuf_printTypeChain (operandType (op), dbuf);
+        if (SPIL_LOC (op) && IS_ITEMP (op))
+          dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname);
+        dbuf_append_char (dbuf, '}');
 
       }
 
       /* if assigned to registers */
       if (OP_SYMBOL (op)->nRegs)
-       {
-         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, "]");
-           }
-       }
-#else
-      fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
-                           OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
+        {
+          if (OP_SYMBOL (op)->isspilt)
+            {
+              if (!OP_SYMBOL (op)->remat)
+                if (OP_SYMBOL (op)->usl.spillLoc)
+                  dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
+                                       OP_SYMBOL (op)->usl.spillLoc->rname :
+                                       OP_SYMBOL (op)->usl.spillLoc->name));
+                else
+                  dbuf_append_str (dbuf, "[err]");
+              else
+                dbuf_append_str (dbuf, "[remat]");
+            }
+          else
+            {
+              int i;
+              dbuf_append_char (dbuf, '[');
+              for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
+                dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
+              dbuf_append_char (dbuf, ']');
+            }
+        }
+//#else         /* } else { */
+    } else {
+      /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
+      dbuf_printf (dbuf, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
+
+      if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
+        {
+          dbuf_printf (dbuf, "[lr%d:%d so:%d]",
+               OP_LIVEFROM (op), OP_LIVETO (op),
+               OP_SYMBOL (op)->stack);
+        }
+
+      if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
+        {
+          dbuf_append_char (dbuf, '{');
+          dbuf_printTypeChain (operandType (op), dbuf);
+          if (SPIL_LOC (op) && IS_ITEMP (op))
+              dbuf_printf (dbuf, "}{ sir@ %s", SPIL_LOC (op)->rname);
+          dbuf_append_char (dbuf, '}');
+        }
+
       /* if assigned to registers */
-      if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
-       {
-         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, "]");
-       }
-#endif
+      if (OP_SYMBOL (op)->nRegs)
+        {
+          if (OP_SYMBOL (op)->isspilt)
+            {
+              if (!OP_SYMBOL (op)->remat)
+                if (OP_SYMBOL (op)->usl.spillLoc)
+                  dbuf_printf (dbuf, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
+                                       OP_SYMBOL (op)->usl.spillLoc->rname :
+                                       OP_SYMBOL (op)->usl.spillLoc->name));
+                else
+                  dbuf_append_str (dbuf, "[err]");
+              else
+                dbuf_append_str (dbuf, "[remat]");
+            }
+          else
+            {
+              int i;
+              dbuf_append_char (dbuf, '[');
+              for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
+                dbuf_printf (dbuf, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
+              dbuf_append_char (dbuf, ']');
+            }
+        }
+//#endif                /* } */
+    }
       break;
 
     case TYPE:
-      fprintf (file, "(");
-      printTypeChain (op->operand.typeOperand, file);
-      fprintf (file, ")");
+      dbuf_append_char (dbuf, '(');
+      dbuf_printTypeChain (op->operand.typeOperand, dbuf);
+      dbuf_append_char (dbuf, ')');
       break;
     }
 
-  if (pnl)
-    fprintf (file, "\n");
   return 0;
 }
 
@@ -304,172 +287,196 @@ printOperand (operand * op, FILE * file)
 /*-----------------------------------------------------------------*/
 PRINTFUNC (picGetValueAtAddr)
 {
-  fprintf (of, "\t");
-  printOperand (IC_RESULT (ic), of);
-  fprintf (of, " = ");
-  fprintf (of, "@[");
-  printOperand (IC_LEFT (ic), of);
-  fprintf (of, "]");
-
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printOperand (IC_RESULT (ic), dbuf);
+  dbuf_append_str (dbuf, " = ");
+  dbuf_append_str (dbuf, "@[");
+  dbuf_printOperand (IC_LEFT (ic), dbuf);
+  dbuf_append_str (dbuf, "]\n");
 }
 
 PRINTFUNC (picSetValueAtAddr)
 {
-  fprintf (of, "\t");
-  fprintf (of, "*[");
-  printOperand (IC_LEFT (ic), of);
-  fprintf (of, "] = ");
-  printOperand (IC_RIGHT (ic), of);
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\t');
+  dbuf_append_str (dbuf, "*[");
+  dbuf_printOperand (IC_LEFT (ic), dbuf);
+  dbuf_append_str (dbuf, "] = ");
+  dbuf_printOperand (IC_RIGHT (ic), dbuf);
+  dbuf_append_char (dbuf, '\n');
 }
 
 PRINTFUNC (picAddrOf)
 {
-  fprintf (of, "\t");
-  printOperand (IC_RESULT (ic), of);
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printOperand (IC_RESULT (ic), dbuf);
   if (IS_ITEMP (IC_LEFT (ic)))
-    fprintf (of, " = ");
+    dbuf_append_str (dbuf, " = ");
   else
-    fprintf (of, " = &[");
-  printOperand (IC_LEFT (ic), of);
+    dbuf_append_str (dbuf, " = &[");
+  dbuf_printOperand (IC_LEFT (ic), dbuf);
   if (IC_RIGHT (ic))
     {
       if (IS_ITEMP (IC_LEFT (ic)))
-       fprintf (of, " offsetAdd ");
+        dbuf_append_str (dbuf, " offsetAdd ");
       else
-       fprintf (of, " , ");
-      printOperand (IC_RIGHT (ic), of);
+        dbuf_append_str (dbuf, " , ");
+      dbuf_printOperand (IC_RIGHT (ic), dbuf);
     }
   if (IS_ITEMP (IC_LEFT (ic)))
-    fprintf (of, "\n");
+    dbuf_append_char (dbuf, '\n');
   else
-    fprintf (of, "]\n");
+    dbuf_append_str (dbuf, "]\n");
 }
 
 PRINTFUNC (picJumpTable)
 {
   symbol *sym;
 
-  fprintf (of, "\t");
-  fprintf (of, "%s\t", s);
-  printOperand (IC_JTCOND (ic), of);
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printf (dbuf, "%s\t", s);
+  dbuf_printOperand (IC_JTCOND (ic), dbuf);
   for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
        sym = setNextItem (IC_JTLABELS (ic)))
-    fprintf (of, "\t\t\t%s\n", sym->name);
+    dbuf_printf (dbuf, "; %s", sym->name);
+  dbuf_append_char (dbuf, '\n');
 }
 
 PRINTFUNC (picGeneric)
 {
-  fprintf (of, "\t");
-  printOperand (IC_RESULT (ic), of);
-  fprintf (of, " = ");
-  printOperand (IC_LEFT (ic), of);
-  fprintf (of, " %s ", s);
-  printOperand (IC_RIGHT (ic), of);
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printOperand (IC_RESULT (ic), dbuf);
+  dbuf_append_str (dbuf, " = ");
+  dbuf_printOperand (IC_LEFT (ic), dbuf);
+  dbuf_printf (dbuf, " %s ", s);
+  dbuf_printOperand (IC_RIGHT (ic), dbuf);
+  dbuf_append_char (dbuf, '\n');
 }
 
 PRINTFUNC (picGenericOne)
 {
-  fprintf (of, "\t");
+  dbuf_append_char (dbuf, '\t');
   if (IC_RESULT (ic))
     {
-      printOperand (IC_RESULT (ic), of);
-      fprintf (of, " = ");
+      dbuf_printOperand (IC_RESULT (ic), dbuf);
+      dbuf_append_str (dbuf, " = ");
     }
 
   if (IC_LEFT (ic))
     {
-      fprintf (of, "%s ", s);
-      printOperand (IC_LEFT (ic), of);
+      dbuf_printf (dbuf, "%s ", s);
+      dbuf_printOperand (IC_LEFT (ic), dbuf);
     }
 
   if (!IC_RESULT (ic) && !IC_LEFT (ic))
-    fprintf (of, s);
+    dbuf_append_str (dbuf, s);
 
   if (ic->op == SEND || ic->op == RECEIVE) {
-      fprintf(of,"{argreg = %d}",ic->argreg);
+      dbuf_printf (dbuf,"{argreg = %d}",ic->argreg);
+  }
+  if (ic->op == IPUSH) {
+      dbuf_printf (dbuf,"{parmPush = %d}",ic->parmPush);
   }
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\n');
 }
 
 PRINTFUNC (picCast)
 {
-  fprintf (of, "\t");
-  printOperand (IC_RESULT (ic), of);
-  fprintf (of, " = ");
-  printOperand (IC_LEFT (ic), of);
-  printOperand (IC_RIGHT (ic), of);
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printOperand (IC_RESULT (ic), dbuf);
+  dbuf_append_str (dbuf, " = ");
+  dbuf_printOperand (IC_LEFT (ic), dbuf);
+  dbuf_printOperand (IC_RIGHT (ic), dbuf);
+  dbuf_append_char (dbuf, '\n');
 }
 
 
 PRINTFUNC (picAssign)
 {
-  fprintf (of, "\t");
+  dbuf_append_char (dbuf, '\t');
 
   if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
-    fprintf (of, "*(");
+    dbuf_append_str (dbuf, "*(");
 
-  printOperand (IC_RESULT (ic), of);
+  dbuf_printOperand (IC_RESULT (ic), dbuf);
 
   if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
-    fprintf (of, ")");
+    dbuf_append_char (dbuf, ')');
 
-  fprintf (of, " %s ", s);
-  printOperand (IC_RIGHT (ic), of);
+  dbuf_printf (dbuf, " %s ", s);
+  dbuf_printOperand (IC_RIGHT (ic), dbuf);
 
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\n');
 }
 
 PRINTFUNC (picLabel)
 {
-  fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
+  dbuf_printf (dbuf, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
 }
 
 PRINTFUNC (picGoto)
 {
-  fprintf (of, "\t");
-  fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printf (dbuf, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
 }
 
 PRINTFUNC (picIfx)
 {
-  fprintf (of, "\t");
-  fprintf (of, "if ");
-  printOperand (IC_COND (ic), of);
+  dbuf_append_char (dbuf, '\t');
+  dbuf_append_str (dbuf, "if ");
+  dbuf_printOperand (IC_COND (ic), dbuf);
 
   if (!IC_TRUE (ic))
-    fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
+    dbuf_printf (dbuf, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
   else
     {
-      fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
+      dbuf_printf (dbuf, " != 0 goto %s($%d)", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
       if (IC_FALSE (ic))
-       fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
+        dbuf_printf (dbuf, "; zzgoto %s\n", IC_FALSE (ic)->name);
+      dbuf_append_char (dbuf, '\n');
     }
 }
 
 PRINTFUNC (picInline)
 {
-  fprintf (of, "%s", IC_INLINE (ic));
+  dbuf_append_str (dbuf, IC_INLINE (ic));
 }
 
 PRINTFUNC (picReceive)
 {
-  printOperand (IC_RESULT (ic), of);
-  fprintf (of, " = %s ", s);
-  printOperand (IC_LEFT (ic), of);
-  fprintf (of, "\n");
+  dbuf_printOperand (IC_RESULT (ic), dbuf);
+  dbuf_printf (dbuf, " = %s ", s);
+  dbuf_printOperand (IC_LEFT (ic), dbuf);
+  dbuf_append_char (dbuf, '\n');
 }
 
 PRINTFUNC (picDummyRead)
 {
-  fprintf (of, "\t");
-  fprintf (of, "%s ", s);
-  printOperand (IC_RIGHT (ic), of);
-  fprintf (of, "\n");
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printf (dbuf, "%s ", s);
+  dbuf_printOperand (IC_RIGHT (ic), dbuf);
+  dbuf_append_char (dbuf, '\n');
+}
+
+PRINTFUNC (picCritical)
+{
+  dbuf_append_char (dbuf, '\t');
+  if (IC_RESULT (ic))
+    dbuf_printOperand (IC_RESULT (ic), dbuf);
+  else
+    dbuf_append_str (dbuf, "(stack)");
+  dbuf_printf (dbuf, " = %s ", s);
+  dbuf_append_char (dbuf, '\n');
+}
+
+PRINTFUNC (picEndCritical)
+{
+  dbuf_append_char (dbuf, '\t');
+  dbuf_printf (dbuf, "%s = ", s);
+  if (IC_RIGHT (ic))
+    dbuf_printOperand (IC_RIGHT (ic), dbuf);
+  else
+    dbuf_append_str (dbuf, "(stack)");
+  dbuf_append_char (dbuf, '\n');
 }
 
 /*-----------------------------------------------------------------*/
@@ -480,21 +487,24 @@ piCode (void *item, FILE * of)
 {
   iCode *ic = item;
   iCodeTable *icTab;
+  struct dbuf_s dbuf;
 
   if (!of)
     of = stdout;
 
   icTab = getTableEntry (ic->op);
-  fprintf (stdout, "%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);
+  fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
+           ic->filename, ic->lineno,
+           ic->seq, ic->key, ic->depth, ic->supportRtn);
+  dbuf_init (&dbuf, 1024);
+  icTab->iCodePrint (&dbuf, ic, icTab->printName);
+  dbuf_write_and_destroy (&dbuf, of);
   return 1;
 }
 
 void PICC(iCode *ic)
 {
-       printiCChain(ic,stdout);
+        printiCChain(ic,stdout);
 }
 /*-----------------------------------------------------------------*/
 /* printiCChain - prints intermediate code for humans              */
@@ -504,19 +514,24 @@ printiCChain (iCode * icChain, FILE * of)
 {
   iCode *loop;
   iCodeTable *icTab;
+  struct dbuf_s dbuf;
 
   if (!of)
     of = stdout;
   for (loop = icChain; loop; loop = loop->next)
     {
       if ((icTab = getTableEntry (loop->op)))
-       {
-         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);
-
-         icTab->iCodePrint (of, loop, icTab->printName);
-       }
+        {
+          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);
+
+          dbuf_init(&dbuf, 1024);
+          icTab->iCodePrint (&dbuf, loop, icTab->printName);
+          dbuf_write_and_destroy (&dbuf, of);
+          ////
+          fflush(of);
+        }
     }
 }
 
@@ -545,8 +560,9 @@ newiCode (int op, operand * left, operand * right)
 
   ic = Safe_alloc ( sizeof (iCode));
 
-  ic->lineno = lineno;
+  ic->seqPoint = seqPoint;
   ic->filename = filename;
+  ic->lineno = lineno;
   ic->block = block;
   ic->level = scopeLevel;
   ic->op = op;
@@ -562,8 +578,8 @@ newiCode (int op, operand * left, operand * right)
 /*-----------------------------------------------------------------*/
 iCode *
 newiCodeCondition (operand * condition,
-                  symbol * trueLabel,
-                  symbol * falseLabel)
+                   symbol * trueLabel,
+                   symbol * falseLabel)
 {
   iCode *ic;
 
@@ -611,7 +627,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;
@@ -627,13 +643,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
     {
@@ -649,14 +665,15 @@ newiTempLabel (char *s)
 }
 
 /*-----------------------------------------------------------------*/
-/* newiTempPreheaderLabel - creates a new preheader label          */
+/* newiTempLoopHeaderLabel - creates a new loop header label       */
 /*-----------------------------------------------------------------*/
 symbol *
-newiTempPreheaderLabel ()
+newiTempLoopHeaderLabel (bool pre)
 {
   symbol *itmplbl;
 
-  SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
+  SNPRINTF (buffer, sizeof(buffer), pre ? "preHeaderLbl%d" : LOOPEXITLBL "%d",
+            iTempLblNum++);
   itmplbl = newSymbol (buffer, 1);
 
   itmplbl->isitmp = 1;
@@ -670,7 +687,7 @@ newiTempPreheaderLabel ()
 /*-----------------------------------------------------------------*/
 /* initiCode - initialises some iCode related stuff                */
 /*-----------------------------------------------------------------*/
-void 
+void
 initiCode ()
 {
 
@@ -684,8 +701,8 @@ copyiCode (iCode * ic)
 {
   iCode *nic = newiCode (ic->op, NULL, NULL);
 
-  nic->lineno = ic->lineno;
   nic->filename = ic->filename;
+  nic->lineno = ic->lineno;
   nic->block = ic->block;
   nic->level = ic->level;
   nic->parmBytes = ic->parmBytes;
@@ -763,7 +780,7 @@ newiTempOperand (sym_link * type, char throwType)
   /* copy the type information */
   if (type)
     itmp->etype = getSpec (itmp->type = (throwType ? type :
-                                        copyLinkChain (type)));
+                                         copyLinkChain (type)));
   if (IS_LITERAL (itmp->etype))
     {
       SPEC_SCLS (itmp->etype) = S_REGISTER;
@@ -784,7 +801,6 @@ operandType (operand * op)
   /* depending on type of operand */
   switch (op->type)
     {
-
     case VALUE:
       return op->operand.valOperand->type;
 
@@ -793,30 +809,49 @@ operandType (operand * op)
 
     case TYPE:
       return op->operand.typeOperand;
+
     default:
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-             " operand type not known ");
-      assert (0);              /* should never come here */
+              " operand type not known ");
+      assert (0);               /* should never come here */
       /*  Just to keep the compiler happy */
       return (sym_link *) 0;
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* operandSize - returns size of an operand in bytes               */
+/*-----------------------------------------------------------------*/
+unsigned int
+operandSize (operand * op)
+{
+  sym_link *type;
+
+  /* if nothing return 0 */
+  if (!op)
+    return 0;
+
+  type = operandType (op);
+  if (op->aggr2ptr == 2)
+    type = type->next;
+  return getSize (type);
+}
+
 /*-----------------------------------------------------------------*/
 /* 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 &&
-         isSymbolEqual (op->operand.symOperand, tval->sym))
-       return 1;
+          isSymbolEqual (op->operand.symOperand, tval->sym))
+        return 1;
       tval = tval->next;
     }
   return 0;
@@ -825,7 +860,7 @@ isParameterToCall (value * args, operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandGlobal   - return 1 if operand is a global variable    */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandGlobal (operand * op)
 {
   if (!op)
@@ -847,7 +882,7 @@ isOperandGlobal (operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandVolatile - return 1 if the operand is volatile         */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandVolatile (operand * op, bool chkTemp)
 {
   sym_link *optype;
@@ -857,19 +892,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;
@@ -888,7 +923,7 @@ isOperandLiteral (operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandInFarSpace - will return true if operand is in farSpace */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isOperandInFarSpace (operand * op)
 {
   sym_link *etype;
@@ -902,9 +937,9 @@ isOperandInFarSpace (operand * op)
   if (!IS_TRUE_SYMOP (op))
     {
       if (SPIL_LOC (op))
-       etype = SPIL_LOC (op)->etype;
+        etype = SPIL_LOC (op)->etype;
       else
-       return FALSE;
+        return FALSE;
     }
   else
     {
@@ -913,10 +948,38 @@ isOperandInFarSpace (operand * op)
   return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
 }
 
+/*-----------------------------------------------------------------*/
+/* isOperandInPagedSpace - return true if operand is in pagedSpace */
+/*-----------------------------------------------------------------*/
+bool
+isOperandInPagedSpace (operand * op)
+{
+  sym_link *etype;
+
+  if (!op)
+    return FALSE;
+
+  if (!IS_SYMOP (op))
+    return FALSE;
+
+  if (!IS_TRUE_SYMOP (op))
+    {
+      if (SPIL_LOC (op))
+        etype = SPIL_LOC (op)->etype;
+      else
+        return FALSE;
+    }
+  else
+    {
+      etype = getSpec (operandType (op));
+    }
+  return (IN_PAGEDSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
 /*------------------------------------------------------------------*/
 /* isOperandInDirSpace - will return true if operand is in dirSpace */
 /*------------------------------------------------------------------*/
-bool 
+bool
 isOperandInDirSpace (operand * op)
 {
   sym_link *etype;
@@ -930,9 +993,9 @@ isOperandInDirSpace (operand * op)
   if (!IS_TRUE_SYMOP (op))
     {
       if (SPIL_LOC (op))
-       etype = SPIL_LOC (op)->etype;
+        etype = SPIL_LOC (op)->etype;
       else
-       return FALSE;
+        return FALSE;
     }
   else
     {
@@ -944,7 +1007,7 @@ isOperandInDirSpace (operand * op)
 /*--------------------------------------------------------------------*/
 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
 /*--------------------------------------------------------------------*/
-bool 
+bool
 isOperandInCodeSpace (operand * op)
 {
   sym_link *etype;
@@ -960,9 +1023,9 @@ isOperandInCodeSpace (operand * op)
   if (!IS_TRUE_SYMOP (op))
     {
       if (SPIL_LOC (op))
-       etype = SPIL_LOC (op)->etype;
+        etype = SPIL_LOC (op)->etype;
       else
-       return FALSE;
+        return FALSE;
     }
   else
     {
@@ -974,7 +1037,7 @@ isOperandInCodeSpace (operand * op)
 /*-----------------------------------------------------------------*/
 /* isOperandOnStack - will return true if operand is on stack      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isOperandOnStack (operand * op)
 {
   sym_link *etype;
@@ -994,6 +1057,55 @@ 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);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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                   */
 /*-----------------------------------------------------------------*/
@@ -1015,13 +1127,13 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
     *pcount = 0;
     /* builtin functions uses only SEND for parameters */
     while (ic->op != CALL) {
-       assert(ic->op == SEND && ic->builtinSEND);
-       ic->generated = 1;    /* mark the icode as generated */
-       parms[*pcount] = IC_LEFT(ic);
-       ic = ic->next;
-       (*pcount)++;
+        assert(ic->op == SEND && ic->builtinSEND);
+        ic->generated = 1;    /* mark the icode as generated */
+        parms[*pcount] = IC_LEFT(ic);
+        ic = ic->next;
+        (*pcount)++;
     }
-    
+
     ic->generated = 1;
     /* make sure this is a builtin function call */
     assert(IS_SYMOP(IC_LEFT(ic)));
@@ -1035,7 +1147,7 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
 /*-----------------------------------------------------------------*/
 operand *
 operandOperation (operand * left, operand * right,
-                 int op, sym_link * type)
+                  int op, sym_link * type)
 {
   sym_link *let , *ret=NULL;
   operand *retval = (operand *) 0;
@@ -1051,19 +1163,19 @@ operandOperation (operand * left, operand * right,
     {
     case '+':
       retval = operandFromValue (valCastLiteral (type,
-                                                operandLitValue (left) +
-                                                operandLitValue (right)));
+                                                 operandLitValue (left) +
+                                                 operandLitValue (right)));
       break;
     case '-':
       retval = operandFromValue (valCastLiteral (type,
-                                                operandLitValue (left) -
-                                                operandLitValue (right)));
+                                                 operandLitValue (left) -
+                                                 operandLitValue (right)));
       break;
     case '*':
       /*
       retval = operandFromValue (valCastLiteral (type,
-                                                operandLitValue (left) *
-                                                operandLitValue (right)));
+                                                 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
@@ -1078,167 +1190,210 @@ operandOperation (operand * left, operand * right,
       if (IS_INT (type) ||
           !IS_SPEC (type))
         {
-         /* long is handled here, because it can overflow with double */
-         if (SPEC_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 (SPEC_USIGN (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 (!options.lessPedantic &&
-                 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 (!options.lessPedantic &&
-                 l != (TYPE_WORD) l)
-               werror (W_INT_OVL);
-           }
-       }
+          /* 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_TARGET_ULONG) double2ul (operandLitValue (left)) *
+                     (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))));
+          else if (IS_UNSIGNED (type)) /* unsigned int */
+            {
+              /* unsigned int is handled here in order to detect overflow */
+              TYPE_TARGET_ULONG ul = (TYPE_TARGET_UINT) double2ul (operandLitValue (left)) *
+                                     (TYPE_TARGET_UINT) double2ul (operandLitValue (right));
+
+              retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_UINT) ul));
+              if (ul != (TYPE_TARGET_UINT) ul)
+                werror (W_INT_OVL);
+            }
+          else /* signed int */
+            {
+              /* signed int is handled here in order to detect overflow */
+              TYPE_TARGET_LONG l = (TYPE_TARGET_INT) operandLitValue (left) *
+                                   (TYPE_TARGET_INT) operandLitValue (right);
+
+              retval = operandFromValue (valCastLiteral (type, (TYPE_TARGET_INT) l));
+              if (l != (TYPE_TARGET_INT) l)
+                werror (W_INT_OVL);
+            }
+        }
       else
-       /* all others go here: */
-       retval = operandFromValue (valCastLiteral (type,
-                                                  operandLitValue (left) *
-                                                  operandLitValue (right)));
+        /* all others go here: */
+        retval = operandFromValue (valCastLiteral (type,
+                                                   operandLitValue (left) *
+                                                   operandLitValue (right)));
       break;
     case '/':
-      if ((TYPE_UDWORD) operandLitValue (right) == 0)
-       {
-         werror (E_DIVIDE_BY_ZERO);
-         retval = right;
-
-       }
+      if (IS_UNSIGNED (type))
+        {
+          if ((TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) == 0)
+            {
+              werror (E_DIVIDE_BY_ZERO);
+              retval = right;
+            }
+          SPEC_USIGN (let) = 1;
+          SPEC_USIGN (ret) = 1;
+          retval = operandFromValue (valCastLiteral (type,
+                                    (TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) /
+                                    (TYPE_TARGET_ULONG) double2ul (operandLitValue (right))));
+        }
       else
-       retval = operandFromValue (valCastLiteral (type,
-                                                  operandLitValue (left) /
-                                                  operandLitValue (right)));
+        {
+          if (operandLitValue (right) == 0)
+            {
+              werror (E_DIVIDE_BY_ZERO);
+              retval = right;
+            }
+          retval = operandFromValue (valCastLiteral (type,
+                                                 operandLitValue (left) /
+                                                 operandLitValue (right)));
+        }
       break;
     case '%':
-      if ((TYPE_UDWORD) operandLitValue (right) == 0) {
-         werror (E_DIVIDE_BY_ZERO);
-         retval = right;
-      }
+      if ((TYPE_TARGET_ULONG) double2ul (operandLitValue (right)) == 0)
+        {
+          werror (E_DIVIDE_BY_ZERO);
+          retval = right;
+        }
       else
         {
-          if (SPEC_USIGN(let) || SPEC_USIGN(ret))
-           /* one of the operands is unsigned */
-           retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
-                                    (TYPE_UDWORD) operandLitValue (right));
-         else
-           /* both operands are signed */
-           retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
-                                    (TYPE_DWORD) operandLitValue (right));
+          if (IS_UNSIGNED (type))
+            retval = operandFromLit ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) %
+                                     (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)));
+          else
+            retval = operandFromLit ((TYPE_TARGET_LONG) operandLitValue (left) %
+                                     (TYPE_TARGET_LONG) operandLitValue (right));
         }
       break;
     case LEFT_OP:
       /* The number of left shifts is always unsigned. Signed doesn't make
-        sense here. Shifting by a negative number is impossible. */
-      retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) <<
-                              (TYPE_UDWORD) operandLitValue (right));
+         sense here. Shifting by a negative number is impossible. */
+      retval = operandFromValue (valCastLiteral (type,
+                                 ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) <<
+                                  (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)))));
       break;
     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 (SPEC_USIGN(let))
+         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));
+        retval = operandFromLit ((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)) >>
+                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)));
       else
         /* signed: arithmetic shift right */
-        retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
-                                (TYPE_UDWORD) operandLitValue (right));
+        retval = operandFromLit ((TYPE_TARGET_LONG) operandLitValue (left) >>
+                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue (right)));
       break;
     case EQ_OP:
-      /* this op doesn't care about signedness */
-      {
-       TYPE_UDWORD l, r;
-
-       l = (TYPE_UDWORD) operandLitValue (left);
-       if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR)
-         l &= 0xff;
-       else if (!SPEC_LONG (OP_VALUE(left)->type))
-         l &= 0xffff;
-       r = (TYPE_UDWORD) operandLitValue (right);
-       if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR)
-         r &= 0xff;
-       else if (!SPEC_LONG (OP_VALUE(right)->type))
-         r &= 0xffff;
-       retval = operandFromLit (l == r);
-      }
+      if (IS_FLOAT (let) || IS_FLOAT (ret))
+        {
+          retval = operandFromLit (operandLitValue (left) ==
+                                   operandLitValue (right));
+        }
+      else if (IS_FIXED16X16 (let) || IS_FIXED16X16 (ret))
+        {
+          retval = operandFromLit (operandLitValue (left) ==
+                                   operandLitValue (right));
+        }
+      else
+        {
+          /* this op doesn't care about signedness */
+          TYPE_TARGET_ULONG l, r;
+
+          l = (TYPE_TARGET_ULONG) double2ul (operandLitValue (left));
+          r = (TYPE_TARGET_ULONG) double2ul (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_TARGET_UINT) r;
+              l = (TYPE_TARGET_UINT) l;
+            }
+          retval = operandFromLit (l == r);
+        }
       break;
     case '<':
       retval = operandFromLit (operandLitValue (left) <
-                              operandLitValue (right));
+                               operandLitValue (right));
       break;
     case LE_OP:
       retval = operandFromLit (operandLitValue (left) <=
-                              operandLitValue (right));
+                               operandLitValue (right));
       break;
     case NE_OP:
       retval = operandFromLit (operandLitValue (left) !=
-                              operandLitValue (right));
+                               operandLitValue (right));
       break;
     case '>':
       retval = operandFromLit (operandLitValue (left) >
-                              operandLitValue (right));
+                               operandLitValue (right));
       break;
     case GE_OP:
       retval = operandFromLit (operandLitValue (left) >=
-                              operandLitValue (right));
+                               operandLitValue (right));
       break;
     case BITWISEAND:
       retval = operandFromValue (valCastLiteral (type,
-                                                 (TYPE_UDWORD)operandLitValue(left) &
-                                                (TYPE_UDWORD)operandLitValue(right)));
+                                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) &
+                                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue(right))));
       break;
     case '|':
       retval = operandFromValue (valCastLiteral (type,
-                                                 (TYPE_UDWORD)operandLitValue(left) |
-                                                (TYPE_UDWORD)operandLitValue(right)));
+                                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) |
+                                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue(right))));
       break;
     case '^':
       retval = operandFromValue (valCastLiteral (type,
-                                                 (TYPE_UDWORD)operandLitValue(left) ^
-                                                (TYPE_UDWORD)operandLitValue(right)));
+                                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) ^
+                                                 (TYPE_TARGET_ULONG) double2ul (operandLitValue(right))));
       break;
     case AND_OP:
       retval = operandFromLit (operandLitValue (left) &&
-                              operandLitValue (right));
+                               operandLitValue (right));
       break;
     case OR_OP:
       retval = operandFromLit (operandLitValue (left) ||
-                              operandLitValue (right));
+                               operandLitValue (right));
       break;
     case RRC:
       {
-       TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
+        TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) double2ul (operandLitValue (left));
 
-       retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
-                                (i << 1));
+        retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
+                                 (i << 1));
       }
       break;
     case RLC:
       {
-       TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
+        TYPE_TARGET_ULONG i = (TYPE_TARGET_ULONG) double2ul (operandLitValue (left));
 
-       retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
-                                (i >> 1));
+        retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
+                                 (i >> 1));
       }
       break;
+    case GETABIT:
+      retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) >>
+                                (TYPE_TARGET_ULONG) double2ul (operandLitValue(right))) & 1);
+      break;
+    case GETBYTE:
+      retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) >>
+                                (TYPE_TARGET_ULONG) double2ul (operandLitValue(right)) & 0xFF));
+      break;
+    case GETWORD:
+      retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) >>
+                                (TYPE_TARGET_ULONG) double2ul (operandLitValue(right)) & 0xFFFF));
+      break;
+
+    case GETHBIT:
+      retval = operandFromLit (((TYPE_TARGET_ULONG) double2ul (operandLitValue(left)) >>
+                                ((getSize (let) * 8) - 1)) & 1);
+      break;
 
     case UNARYMINUS:
       retval = operandFromValue (valCastLiteral (type,
@@ -1246,7 +1401,8 @@ operandOperation (operand * left, operand * right,
       break;
 
     case '~':
-      retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 ~((TYPE_TARGET_ULONG) double2ul (operandLitValue (left)))));
       break;
 
     case '!':
@@ -1255,7 +1411,7 @@ operandOperation (operand * left, operand * right,
 
     default:
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-             " operandOperation invalid operator ");
+              " operandOperation invalid operator ");
       assert (0);
     }
 
@@ -1288,14 +1444,16 @@ isOperandEqual (operand * left, operand * right)
     {
     case SYMBOL:
       return isSymbolEqual (left->operand.symOperand,
-                           right->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)
-       return 1;
+                     right->operand.typeOperand) == 1)
+        return 1;
     }
 
   return 0;
@@ -1304,7 +1462,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 */
@@ -1321,23 +1479,23 @@ isiCodeEqual (iCode * left, iCode * right)
 
       /* compare all the elements depending on type */
       if (left->op != IFX)
-       {
-         if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
-           return 0;
-         if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
-           return 0;
+        {
+          if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
+            return 0;
+          if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
+            return 0;
 
-       }
+        }
       else
-       {
-         if (!isOperandEqual (IC_COND (left), IC_COND (right)))
-           return 0;
-         if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
-           return 0;
-         if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
-           return 0;
-       }
-      
+        {
+          if (!isOperandEqual (IC_COND (left), IC_COND (right)))
+            return 0;
+          if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
+            return 0;
+          if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
+            return 0;
+        }
+
       return 1;
     }
   return 0;
@@ -1454,21 +1612,20 @@ 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;
 
-  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_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 */
+  if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
+      !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 */
+      !sym->islbl &&                    /* not a label */
+      ok                            /* farspace check */
     )
     {
 
@@ -1476,6 +1633,7 @@ operandFromSymbol (symbol * sym)
          and before liveRange calculation */
       sym->reqv = newiTempOperand (sym->type, 0);
       sym->reqv->key = sym->key;
+      OP_SYMBOL (sym->reqv)->prereqv = sym;
       OP_SYMBOL (sym->reqv)->key = sym->key;
       OP_SYMBOL (sym->reqv)->isreqv = 1;
       OP_SYMBOL (sym->reqv)->islocal = 1;
@@ -1598,7 +1756,7 @@ operandFromAst (ast * tree,int lvl)
     default:
       assert (0);
     }
-  
+
   /*  Just to keep the compiler happy */
   return (operand *) 0;
 }
@@ -1606,7 +1764,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 */
@@ -1615,18 +1773,18 @@ setOperandType (operand * op, sym_link * type)
 
     case VALUE:
       op->operand.valOperand->etype =
-       getSpec (op->operand.valOperand->type =
-                copyLinkChain (type));
+        getSpec (op->operand.valOperand->type =
+                 copyLinkChain (type));
       return;
 
     case SYMBOL:
       if (op->operand.symOperand->isitmp)
-       op->operand.symOperand->etype =
-         getSpec (op->operand.symOperand->type =
-                  copyLinkChain (type));
+        op->operand.symOperand->etype =
+          getSpec (op->operand.symOperand->type =
+                   copyLinkChain (type));
       else
-       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-               "attempt to modify type of source");
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                "attempt to modify type of source");
       return;
 
     case TYPE:
@@ -1635,10 +1793,11 @@ setOperandType (operand * op, sym_link * type)
     }
 
 }
+
 /*-----------------------------------------------------------------*/
 /* Get size in byte of ptr need to access an array                 */
 /*-----------------------------------------------------------------*/
-int
+static unsigned int
 getArraySizePtr (operand * op)
 {
   sym_link *ltype = operandType(op);
@@ -1646,29 +1805,32 @@ 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))
     {
       sym_link *letype = getSpec(ltype);
       switch (PTR_TYPE (SPEC_OCLS (letype)))
-       {
-       case IPOINTER:
-       case PPOINTER:
-       case POINTER:
-         return (PTRSIZE);
-       case EEPPOINTER:
-       case FPOINTER:
-       case CPOINTER:
-       case FUNCTION:
-         return (FPTRSIZE);
-       case GPOINTER:
-         return (GPTRSIZE-1);
-
-       default:
-         return (FPTRSIZE);
-       }
+        {
+        case IPOINTER:
+        case PPOINTER:
+        case POINTER:
+          return (PTRSIZE);
+        case EEPPOINTER:
+        case FPOINTER:
+        case CPOINTER:
+        case FUNCTION:
+          return (FPTRSIZE);
+        case GPOINTER:
+          if (GPTRSIZE > FPTRSIZE)
+            return (GPTRSIZE-1);
+          else
+            return (FPTRSIZE);
+
+        default:
+          return (FPTRSIZE);
+        }
     }
   return (FPTRSIZE);
 }
@@ -1676,35 +1838,54 @@ getArraySizePtr (operand * op)
 /*-----------------------------------------------------------------*/
 /* perform "usual unary conversions"                               */
 /*-----------------------------------------------------------------*/
-operand *
+#if 0
+static operand *
 usualUnaryConversions (operand * op)
 {
   if (IS_INTEGRAL (operandType (op)))
     {
       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
-       {
-         /* Widen to int. */
-         return geniCodeCast (INTTYPE, op, TRUE);
-       }
+        {
+          /* Widen to int. */
+          return geniCodeCast (INTTYPE, op, TRUE);
+        }
     }
   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, int op)
 {
   sym_link *ctype;
   sym_link *rtype = operandType (*op2);
   sym_link *ltype = operandType (*op1);
-  
-  ctype = computeType (ltype, rtype);
+
+  ctype = computeType (ltype, rtype, resultType, op);
+
+  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;
 }
 
@@ -1733,7 +1914,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;
@@ -1742,7 +1923,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);
@@ -1766,10 +1947,41 @@ geniCodeRValue (operand * op, bool force)
   return IC_RESULT (ic);
 }
 
+static DECLARATOR_TYPE
+getPtrType(sym_link *type)
+{
+  //for Z80 anything goes
+  if (TARGET_Z80_LIKE)
+    return POINTER;
+
+  //preserve original behaviour for PIC16
+  if (TARGET_IS_PIC16)
+    return POINTER;
+
+  //for HC08 only zeropage ptr is different
+  if (TARGET_IS_HC08)
+    {
+      if (IS_DATA_PTR (type))
+        return POINTER;
+      else
+        return FPOINTER;
+    }
+
+  if (IS_DATA_PTR (type) && TARGET_MCS51_LIKE)
+    return IPOINTER;
+  if (IS_PTR (type))
+    return DCL_TYPE (type);
+  else if (IS_FUNC (type))
+    return CPOINTER;
+  else if (IS_ARRAY (type))
+    return PTR_TYPE (SPEC_OCLS (getSpec (type)));
+  return UPOINTER;
+}
+
 /*-----------------------------------------------------------------*/
 /* geniCodeCast - changes the value from one type to another       */
 /*-----------------------------------------------------------------*/
-operand *
+static operand *
 geniCodeCast (sym_link * type, operand * op, bool implicit)
 {
   iCode *ic;
@@ -1785,66 +1997,84 @@ 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_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
-         if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
-           // no way to set the storage
-           if (IS_LITERAL(optype)) {
-             werror(E_LITERAL_GENERIC);
-             errors++;
-           } else {
-             werror(E_NONPTR2_GENPTR);
-             errors++;
-           }
-         } else if (implicit) {
-           werror(W_INTEGRAL2PTR_NOCAST);
-           errors++;
-         }
-       }
-      }        else { 
-       // shouldn't do that with float, array or structure unless to void
-       if (!IS_VOID(getSpec(type)) && 
-           !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
-         werror(E_INCOMPAT_TYPES);
-         errors++;
-       }
+      if (IS_INTEGRAL(optype)) {
+        // maybe this is NULL, than it's ok.
+        if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
+          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);
+              errors++;
+            } else {
+              werror(E_NONPTR2_GENPTR);
+              errors++;
+            }
+          } else if (implicit) {
+            werror(W_INTEGRAL2PTR_NOCAST);
+            errors++;
+          }
+        }
+      } else {
+        // shouldn't do that with float, array or structure unless to void
+        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 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)))) {
-             werror(E_INCOMPAT_PTYPES);
-             errors++;
-           }
-         }
-       }
+      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)) ||
+                  ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
+                 )
+               )
+            {
+              werror(E_INCOMPAT_PTYPES);
+              errors++;
+            }
+          }
+        }
       }
     }
   } else { // to a non pointer
     if (IS_PTR(optype)) { // from a pointer
       if (implicit) { // sneaky
-       if (IS_INTEGRAL(type)) {
-         werror(W_PTR2INTEGRAL_NOCAST);
-         errors++;
-       } else { // shouldn't do that with float, array or structure
-         werror(E_INCOMPAT_TYPES);
-         errors++;
-       }
+        if (IS_INTEGRAL(type)) {
+          werror(W_PTR2INTEGRAL_NOCAST);
+          errors++;
+        } else { // shouldn't do that with float, array or structure
+          werror(E_INCOMPAT_TYPES);
+          errors++;
+        }
       }
     }
   }
@@ -1853,24 +2083,33 @@ 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 assignment 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) &&
       !IS_FLOAT (optype) &&
+      !IS_FIXED (type) &&
+      !IS_FIXED (optype) &&
       ((IS_SPEC (type) && IS_SPEC (optype)) ||
-       (!IS_SPEC (type) && !IS_SPEC (optype))))
+       (IS_DECL (type) && IS_DECL (optype) && getPtrType (type) == getPtrType (optype))))
     {
-
       ic = newiCode ('=', NULL, op);
       IC_RESULT (ic) = newiTempOperand (type, 0);
-      SPIL_LOC (IC_RESULT (ic)) =
-       (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
+      if (IS_TRUE_SYMOP (op) && !IS_VOLATILE (optype))
+          SPIL_LOC (IC_RESULT (ic)) = OP_SYMBOL (op);
       IC_RESULT (ic)->isaddr = 0;
     }
   else
     {
       ic = newiCode (CAST, operandFromLink (type),
-                    geniCodeRValue (op, FALSE));
+                     geniCodeRValue (op, FALSE));
 
       IC_RESULT (ic) = newiTempOperand (type, 0);
     }
@@ -1878,10 +2117,12 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
   /* preserve the storage class & output class */
   /* of the original variable                  */
   restype = getSpec (operandType (IC_RESULT (ic)));
-  if (!IS_LITERAL(opetype))
+  if (!IS_LITERAL(opetype) &&
+      !IS_BIT(opetype))
+    {
       SPEC_SCLS (restype) = SPEC_SCLS (opetype);
-  SPEC_OCLS (restype) = SPEC_OCLS (opetype);
-
+      SPEC_OCLS (restype) = SPEC_OCLS (opetype);
+    }
   ADDTOCHAIN (ic);
   return IC_RESULT (ic);
 }
@@ -1889,7 +2130,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
 /*-----------------------------------------------------------------*/
 /* geniCodeLabel - will create a Label                             */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeLabel (symbol * label)
 {
   iCode *ic;
@@ -1901,7 +2142,7 @@ geniCodeLabel (symbol * label)
 /*-----------------------------------------------------------------*/
 /* geniCodeGoto  - will create a Goto                              */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeGoto (symbol * label)
 {
   iCode *ic;
@@ -1913,8 +2154,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;
@@ -1924,48 +2165,54 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt)
   /* if they are both literal then we know the result */
   if (IS_LITERAL (letype) && IS_LITERAL (retype))
     return operandFromValue (valMult (left->operand.valOperand,
-                                     right->operand.valOperand));
+                                      right->operand.valOperand));
 
   if (IS_LITERAL(retype)) {
-    p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
+    p2 = powof2 ((TYPE_TARGET_ULONG) ulFromVal (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
      if port has 1 byte muldiv */
-  if (p2 && !IS_FLOAT (letype) &&
-      !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
-       (port->support.muldiv == 1)))
-    {
-      if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
-       {
-         /* LEFT_OP need same size for left and result, */
-         left = geniCodeCast (resType, left, TRUE);
-         ltype = operandType (left);
-       }
+  if ((p2 > 0) && !IS_FLOAT (letype) && !IS_FIXED (letype)
+      && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
+           && (port->support.muldiv == 1))
+      && strcmp (port->target, "pic16") != 0  /* don't shift for pic */
+      && strcmp (port->target, "pic14") != 0)
+    {
+      if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
+        {
+          /* LEFT_OP need same size for left and result, */
+          left = geniCodeCast (resType, left, TRUE);
+          ltype = operandType (left);
+        }
       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
     }
   else
     {
-      ic = newiCode ('*', left, right);                /* normal multiplication */
       /* if the size left or right > 1 then support routine */
       if (getSize (ltype) > 1 || getSize (rtype) > 1)
-       ic->supportRtn = 1;
-
+        {
+          if (IS_LITERAL (retype))
+            ic = newiCode ('*', right, left); /* multiplication by support routine with one literal */
+          else
+            ic = newiCode ('*', left, right); /* multiplication by support routine */
+          ic->supportRtn = 1;
+        }
+      else
+        {
+          ic = newiCode ('*', left, right);   /* normal multiplication */
+        }
     }
   IC_RESULT (ic) = newiTempOperand (resType, 1);
 
@@ -1976,8 +2223,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;
@@ -1987,24 +2234,24 @@ 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
      right shift */
   if (IS_LITERAL (retype) &&
       !IS_FLOAT (letype) &&
-      SPEC_USIGN(letype) &&
-      (p2 = powof2 ((unsigned long)
-                   floatFromVal (right->operand.valOperand)))) {
+      !IS_FIXED (letype) &&
+      IS_UNSIGNED(letype) &&
+      ((p2 = powof2 ((TYPE_TARGET_ULONG) ulFromVal (right->operand.valOperand))) > 0)) {
     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
   }
   else
     {
-      ic = newiCode ('/', left, right);                /* normal division */
+      ic = newiCode ('/', left, right);         /* normal division */
       /* if the size left or right > 1 then support routine */
       if (getSize (ltype) > 1 || getSize (rtype) > 1)
-       ic->supportRtn = 1;
+        ic->supportRtn = 1;
     }
   IC_RESULT (ic) = newiTempOperand (resType, 0);
 
@@ -2014,8 +2261,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;
@@ -2024,9 +2271,9 @@ geniCodeModulus (operand * left, operand * right)
   /* if they are both literal then we know the result */
   if (IS_LITERAL (letype) && IS_LITERAL (retype))
     return operandFromValue (valMod (left->operand.valOperand,
-                                    right->operand.valOperand));
+                                     right->operand.valOperand));
 
-  resType = usualBinaryConversions (&left, &right);
+  resType = usualBinaryConversions (&left, &right, resultType, '%');
 
   /* now they are the same size */
   ic = newiCode ('%', left, right);
@@ -2054,7 +2301,7 @@ geniCodePtrPtrSubtract (operand * left, operand * right)
   if (IS_LITERAL (letype) && IS_LITERAL (retype))
     {
       result = operandFromValue (valMinus (left->operand.valOperand,
-                                          right->operand.valOperand));
+                                           right->operand.valOperand));
       goto subtractExit;
     }
 
@@ -2070,14 +2317,15 @@ subtractExit:
 
   // should we really do this? is this ANSI?
   return geniCodeDivision (result,
-                          operandFromLit (getSize (ltype->next)));
+                           operandFromLit (getSize (ltype->next)),
+                           FALSE);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSubtract - generates code for subtraction               */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeSubtract (operand * left, operand * right)
+static operand *
+geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
   int isarray = 0;
@@ -2093,19 +2341,22 @@ geniCodeSubtract (operand * left, operand * right)
   if (IS_LITERAL (letype) && IS_LITERAL (retype)
       && left->isLiteral && right->isLiteral)
     return operandFromValue (valMinus (left->operand.valOperand,
-                                      right->operand.valOperand));
+                                       right->operand.valOperand));
 
   /* if left is an array or pointer */
   if (IS_PTR (ltype) || IS_ARRAY (ltype))
     {
       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);
+    {                           /* make them the same size */
+      resType = usualBinaryConversions (&left, &right, resultType, '-');
     }
 
   ic = newiCode ('-', left, right);
@@ -2114,7 +2365,8 @@ geniCodeSubtract (operand * left, operand * right)
   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
 
   /* if left or right is a float */
-  if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
+  if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
+      || IS_FIXED (ltype) || IS_FIXED (rtype))
     ic->supportRtn = 1;
 
   ADDTOCHAIN (ic);
@@ -2124,22 +2376,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 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 */
@@ -2147,22 +2400,30 @@ 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, resultType);
+          /* 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);
 
@@ -2171,7 +2432,8 @@ geniCodeAdd (operand * left, operand * right, int lvl)
 
   /* if left or right is a float then support
      routine */
-  if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
+  if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
+      || IS_FIXED (ltype) || IS_FIXED (rtype))
     ic->supportRtn = 1;
 
   ADDTOCHAIN (ic);
@@ -2181,7 +2443,7 @@ geniCodeAdd (operand * left, operand * right, 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)
@@ -2189,7 +2451,6 @@ aggrToPtr (sym_link * type, bool force)
   sym_link *etype;
   sym_link *ptype;
 
-
   if (IS_PTR (type) && !force)
     return type;
 
@@ -2198,43 +2459,35 @@ aggrToPtr (sym_link * type, bool force)
 
   ptype->next = type;
 
-  /* if the output class is code */
-  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;
+  /* set the pointer depending on the storage class */
+  DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
+  return ptype;
+}
 
-  /* the variable was volatile then pointer to volatile */
-  if (IS_VOLATILE (etype))
-    DCL_PTR_VOLATILE (ptype) = 1;
+/*------------------------------------------------------------------*/
+/* 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 ptype;
+  /* return the pointer depending on the storage class */
+  return PTR_TYPE (SPEC_OCLS (getSpec (type)));
 }
 
 /*-----------------------------------------------------------------*/
 /* 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;
-
-  /* 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;
+  DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
 
   op->isaddr = 0;
   return op;
@@ -2244,48 +2497,72 @@ 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;
+  RESULT_TYPE resultType;
 
-  if (IS_PTR (ltype))
+  resultType = (getArraySizePtr(left) >= INTSIZE) ? RESULT_TYPE_INT : RESULT_TYPE_CHAR;
+  if (DCL_ELEM (ltype))
     {
-      if (IS_PTR (ltype->next) && left->isaddr)
-       {
-         left = geniCodeRValue (left, FALSE);
-       }
-      return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
+      if (DCL_ELEM (ltype) * getSize (ltype->next) <= 255)
+        resultType = RESULT_TYPE_CHAR;
     }
 
-  right = geniCodeMultiply (right,
-                           operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+  if (IS_PTR (ltype))
+    {
+      if (IS_PTR (ltype->next) && left->isaddr)
+        {
+          left = geniCodeRValue (left, FALSE);
+        }
 
+      return geniCodeDerefPtr (geniCodeAdd (left, right, resultType, lvl),
+                               lvl);
+    }
+  size = operandFromLit (getSize (ltype->next));
+  SPEC_USIGN (getSpec (operandType (size))) = 1;
+  indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
+  right = geniCodeMultiply (right, size, resultType);
+  /* 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);
 
   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
-                                     !IS_AGGREGATE (ltype->next) &&
-                                     !IS_PTR (ltype->next))
-                                    ? ltype : ltype->next), 0);
+                                      !IS_AGGREGATE (ltype->next) &&
+                                      !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);
 }
 
 /*-----------------------------------------------------------------*/
-/* geniCodeStruct - generates intermediate code for structres      */
+/* geniCodeStruct - generates intermediate code for structures     */
 /*-----------------------------------------------------------------*/
 operand *
 geniCodeStruct (operand * left, operand * right, bool islval)
@@ -2295,10 +2572,10 @@ geniCodeStruct (operand * left, operand * right, bool islval)
   sym_link *etype = getSpec (type);
   sym_link *retype;
   symbol *element = getStructElement (SPEC_STRUCT (etype),
-                                     right->operand.symOperand);
+                                      right->operand.symOperand);
 
   wassert(IS_SYMOP(right));
-    
+
   /* add the offset */
   ic = newiCode ('+', left, operandFromLit (element->offset));
 
@@ -2310,13 +2587,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));
 }
@@ -2332,8 +2609,8 @@ geniCodePostInc (operand * op)
   sym_link *optype = operandType (op);
   operand *result;
   operand *rv = (IS_ITEMP (op) ?
-                geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
-                op);
+                 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+                 op);
   sym_link *rvtype = operandType (rv);
   int size = 0;
 
@@ -2350,18 +2627,22 @@ 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 if (IS_FIXED16X16 (rvtype))
+    ic = newiCode ('+', rv, operandFromValue (constFixed16x16Val ("1.0")));
   else
     ic = newiCode ('+', rv, operandFromLit (size));
 
   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
   ADDTOCHAIN (ic);
 
-  geniCodeAssign (op, result, 0);
+  geniCodeAssign (op, result, 0, 0);
 
   return rOp;
 
@@ -2371,13 +2652,13 @@ geniCodePostInc (operand * op)
 /* geniCodePreInc - generate code for preIncrement                 */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodePreInc (operand * op)
+geniCodePreInc (operand * op, bool lvalue)
 {
   iCode *ic;
   sym_link *optype = operandType (op);
   operand *rop = (IS_ITEMP (op) ?
-                 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
-                 op);
+                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+                  op);
   sym_link *roptype = operandType (rop);
   operand *result;
   int size = 0;
@@ -2388,17 +2669,23 @@ geniCodePreInc (operand * op)
       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 if (IS_FIXED16X16 (roptype))
+    ic = newiCode ('+', rop, operandFromValue (constFixed16x16Val ("1.0")));
   else
     ic = newiCode ('+', rop, operandFromLit (size));
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-
-  return geniCodeAssign (op, result, 0);
+  (void) geniCodeAssign (op, result, 0, 0);
+  if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
+    return op;
+  else
+    return result;
 }
 
 /*-----------------------------------------------------------------*/
@@ -2412,8 +2699,8 @@ geniCodePostDec (operand * op)
   sym_link *optype = operandType (op);
   operand *result;
   operand *rv = (IS_ITEMP (op) ?
-                geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
-                op);
+                 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+                 op);
   sym_link *rvtype = operandType (rv);
   int size = 0;
 
@@ -2430,18 +2717,22 @@ 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 if (IS_FIXED16X16 (rvtype))
+    ic = newiCode ('-', rv, operandFromValue (constFixed16x16Val ("1.0")));
   else
     ic = newiCode ('-', rv, operandFromLit (size));
 
   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
   ADDTOCHAIN (ic);
 
-  geniCodeAssign (op, result, 0);
+  geniCodeAssign (op, result, 0, 0);
 
   return rOp;
 
@@ -2451,13 +2742,13 @@ 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);
   operand *rop = (IS_ITEMP (op) ?
-                 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
-                 op);
+                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+                  op);
   sym_link *roptype = operandType (rop);
   operand *result;
   int size = 0;
@@ -2468,26 +2759,32 @@ geniCodePreDec (operand * op)
       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 if (IS_FIXED16X16 (roptype))
+    ic = newiCode ('-', rop, operandFromValue (constFixed16x16Val ("1.0")));
   else
     ic = newiCode ('-', rop, operandFromLit (size));
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-
-  return geniCodeAssign (op, result, 0);
+  (void) geniCodeAssign (op, result, 0, 0);
+  if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
+    return op;
+  else
+    return result;
 }
 
 
 /*-----------------------------------------------------------------*/
-/* geniCodeBitwise - gen int code for bitWise  operators           */
+/* geniCodeBitwise - gen int code for bitWise operators            */
 /*-----------------------------------------------------------------*/
 operand *
 geniCodeBitwise (operand * left, operand * right,
-                int oper, sym_link * resType)
+                 int oper, sym_link * resType)
 {
   iCode *ic;
 
@@ -2512,6 +2809,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)) { */
@@ -2522,15 +2826,7 @@ geniCodeAddressOf (operand * op)
   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);
 
@@ -2542,17 +2838,18 @@ geniCodeAddressOf (operand * op)
       return op;
     }
 
-  /* other wise make this of the type coming in */
+  /* otherwise make this of the type coming in */
   ic = newiCode (ADDRESS_OF, op, NULL);
   IC_RESULT (ic) = newiTempOperand (p, 1);
   IC_RESULT (ic)->isaddr = 0;
   ADDTOCHAIN (ic);
   return IC_RESULT (ic);
 }
+
 /*-----------------------------------------------------------------*/
 /* setOClass - sets the output class depending on the pointer type */
 /*-----------------------------------------------------------------*/
-void 
+void
 setOClass (sym_link * ptr, sym_link * spec)
 {
   switch (DCL_TYPE (ptr))
@@ -2623,23 +2920,18 @@ geniCodeDerefPtr (operand * op,int lvl)
   else
     {
       retype = getSpec (rtype = copyLinkChain (optype->next));
+      /* outputclass needs 2b updated */
+      setOClass (optype, retype);
     }
 
-  /* outputclass needs 2b updated */
-  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) ||
-               IS_CHAR (rtype) ||
-               IS_FLOAT (rtype));
+                IS_STRUCT (rtype) ||
+                IS_INT (rtype) ||
+                IS_CHAR (rtype) ||
+                IS_FLOAT (rtype) ||
+                IS_FIXED (rtype));
 
   if (!isLvaluereq(lvl))
     op = geniCodeRValue (op, TRUE);
@@ -2671,12 +2963,15 @@ geniCodeUnaryMinus (operand * op)
 /* geniCodeLeftShift - gen i code for left shift                   */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeLeftShift (operand * left, operand * right)
+geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
 {
   iCode *ic;
+  sym_link *resType;
 
   ic = newiCode (LEFT_OP, left, right);
-  IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
+
+  resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
+  IC_RESULT (ic) = newiTempOperand (resType, 0);
   ADDTOCHAIN (ic);
   return IC_RESULT (ic);
 }
@@ -2698,11 +2993,11 @@ geniCodeRightShift (operand * left, operand * right)
 /*-----------------------------------------------------------------*/
 /* geniCodeLogic- logic code                                       */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeLogic (operand * left, operand * right, int op)
+static operand *
+geniCodeLogic (operand * left, operand * right, int op, ast *tree)
 {
   iCode *ic;
-  sym_link *ctype;
+  sym_link *ctype, *ttype;
   sym_link *rtype = operandType (right);
   sym_link *ltype = operandType (left);
 
@@ -2710,14 +3005,68 @@ 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,
-                        OP_VALUE(right), "compare operation", 1);
+      CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE);
+      switch (ccr_result)
+        {
+          case CCR_ALWAYS_TRUE:
+          case CCR_ALWAYS_FALSE:
+            if (!options.lessPedantic)
+              werror (W_COMP_RANGE, "true resp. false");
+            return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0);
+          default:
+            break;
+        }
     }
 
-  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_BIT, 0);
 
   ic = newiCode (op, left, right);
-  IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
+  /* store 0 or 1 in result */
+  ttype = (tree && IS_BIT (tree->ftype)) ? newBoolLink() : newCharLink();
+  IC_RESULT (ic) = newiTempOperand (ttype, 1);
 
   /* if comparing float
      and not a '==' || '!=' || '&&' || '||' (these
@@ -2727,6 +3076,10 @@ geniCodeLogic (operand * left, operand * right, int op)
       op != NE_OP &&
       op != AND_OP &&
       op != OR_OP)
+   ic->supportRtn = 1;
+
+  /* if comparing a fixed type use support functions */
+  if (IS_FIXED(ctype))
     ic->supportRtn = 1;
 
   ADDTOCHAIN (ic);
@@ -2734,7 +3087,74 @@ geniCodeLogic (operand * left, operand * right, int op)
 }
 
 /*-----------------------------------------------------------------*/
-/* geniCodeUnary - for a a generic unary operation                 */
+/* geniCodeLogicAndOr - && || operations                           */
+/*-----------------------------------------------------------------*/
+static operand *
+geniCodeLogicAndOr (ast *tree, int lvl)
+{
+  iCode *ic;
+  sym_link *type;
+  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 */
+  type = (IS_BIT (tree->ftype)) ? newBoolLink() : newCharLink();
+  result = newiTempOperand (type, 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 generic unary operation                   */
 /*-----------------------------------------------------------------*/
 operand *
 geniCodeUnary (operand * op, int oper)
@@ -2746,6 +3166,19 @@ geniCodeUnary (operand * op, int oper)
   return IC_RESULT (ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* geniCodeBinary - for a generic binary operation                 */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeBinary (operand * left, operand * right, int oper)
+{
+  iCode *ic = newiCode (oper, left, right);
+
+  IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
+}
+
 /*-----------------------------------------------------------------*/
 /* geniCodeConditional - geniCode for '?' ':' operation            */
 /*-----------------------------------------------------------------*/
@@ -2755,18 +3188,19 @@ geniCodeConditional (ast * tree,int lvl)
   iCode *ic;
   symbol *falseLabel = newiTempLabel (NULL);
   symbol *exitLabel = newiTempLabel (NULL);
-  operand *cond = ast2iCode (tree->left,lvl+1);
-  operand *true, *false, *result;
+  ast *astTrue  = tree->right->left;
+  ast *astFalse = tree->right->right;
+  operand *cond = ast2iCode (tree->left, lvl+1);
+  operand *result = newiTempOperand (tree->ftype, 0);
+  operand *opTrue, *opFalse;
 
-  ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
-                         NULL, falseLabel);
+  ic = newiCodeCondition (geniCodeRValue (cond, FALSE), NULL, falseLabel);
   ADDTOCHAIN (ic);
 
-  true = ast2iCode (tree->right->left,lvl+1);
+  opTrue = ast2iCode (astTrue, lvl+1);
 
-  /* move the value to a new Operand */
-  result = newiTempOperand (tree->right->ftype, 0);
-  geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
+  /* move the value to the new operand */
+  geniCodeAssign (result, geniCodeRValue (opTrue, FALSE), 0, 0);
 
   /* generate an unconditional goto */
   geniCodeGoto (exitLabel);
@@ -2774,8 +3208,8 @@ geniCodeConditional (ast * tree,int lvl)
   /* now for the right side */
   geniCodeLabel (falseLabel);
 
-  false = ast2iCode (tree->right->right,lvl+1);
-  geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
+  opFalse = ast2iCode (astFalse, lvl+1);
+  geniCodeAssign (result, geniCodeRValue (opFalse, FALSE), 0, 0);
 
   /* create the exit label */
   geniCodeLabel (exitLabel);
@@ -2787,13 +3221,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;
@@ -2801,10 +3235,11 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
 
   /* left is integral type and right is literal then
      check if the literal value is within bounds */
-  if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
+  if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) &&
+      checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL &&
+      !options.lessPedantic)
     {
-      checkConstantRange(ltype, 
-                        OP_VALUE(right), "= operation", 0);
+      werror (W_LIT_OVERFLOW);
     }
 
   /* if the left & right type don't exactly match */
@@ -2816,28 +3251,35 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
       compareType (ltype, rtype) <= 0)
     {
-      if (compareType (ltype->next, rtype) < 0)
-       right = geniCodeCast (ltype->next, right, TRUE);
+      if (left->aggr2ptr)
+        right = geniCodeCast (ltype, right, TRUE);
+      else if (compareType (ltype->next, rtype) < 0)
+        right = geniCodeCast (ltype->next, right, TRUE);
     }
   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))
     {
       symbol *sym = NULL;
+      operand *newRight;
 
       if (IS_TRUE_SYMOP (right))
-       sym = OP_SYMBOL (right);
+        sym = OP_SYMBOL (right);
       ic = newiCode ('=', NULL, right);
-      IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
-      SPIL_LOC (right) = sym;
+      IC_RESULT (ic) = newRight = newiTempOperand (ltype, 0);
+      /* avoid double fetch from volatile right, see bug 1369874 */
+      if (!isOperandVolatile (right, FALSE))
+        SPIL_LOC (newRight) = sym;
+      right = newRight;
       ADDTOCHAIN (ic);
     }
 
@@ -2851,13 +3293,33 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
     ic->supportRtn = 1;
 
   ic->nosupdate = nosupdate;
-  return left;
+  /* left could be a pointer assignment,
+     return the properly casted right instead */
+  return right;
+}
+
+/*-----------------------------------------------------------------*/
+/* 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       */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeSEParms (ast * parms,int lvl)
 {
   if (!parms)
@@ -2880,20 +3342,20 @@ 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);
+                SPEC_ARGREG(parms->ftype);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeParms - generates parameters                            */
 /*-----------------------------------------------------------------*/
 value *
-geniCodeParms (ast * parms, value *argVals, int *stack, 
-              sym_link * fetype, symbol * func,int lvl)
+geniCodeParms (ast * parms, value *argVals, int *stack,
+               sym_link * ftype, int lvl)
 {
   iCode *ic;
   operand *pval;
@@ -2903,14 +3365,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;
     }
 
@@ -2923,47 +3385,47 @@ 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);
     }
 
   /* 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)))
-       {
-
-         /* 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);
-       }
+      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, 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;
@@ -2979,12 +3441,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)) {
+  if (!IS_FUNC(OP_SYMBOL(left)->type) &&
+      !IS_FUNCPTR(OP_SYMBOL(left)->type)) {
     werror (E_FUNCTION_EXPECTED);
-    return NULL;
+    return operandFromValue(valueFromLit(0));
   }
 
   /* take care of parameters with side-effecting
@@ -2992,8 +3455,12 @@ geniCodeCall (operand * left, ast * parms,int lvl)
      of overlaying function parameters */
   geniCodeSEParms (parms,lvl);
 
+  ftype = operandType (left);
+  if (IS_FUNCPTR (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)) {
@@ -3002,7 +3469,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);
@@ -3018,51 +3485,62 @@ geniCodeCall (operand * left, ast * parms,int lvl)
 /*-----------------------------------------------------------------*/
 /* geniCodeReceive - generate intermediate code for "receive"      */
 /*-----------------------------------------------------------------*/
-static void 
-geniCodeReceive (value * args)
+static void
+geniCodeReceive (value * args, operand * func)
 {
+  unsigned char paramByteCounter = 0;
+
   /* for all arguments that are passed in registers */
   while (args)
     {
-      int first = 1;
       if (IS_REGPARM (args->etype))
-       {
-         operand *opr = operandFromValue (args);
-         operand *opl;
-         symbol *sym = OP_SYMBOL (opr);
-         iCode *ic;
-
-         /* we will use it after all optimizations
-            and before liveRange calculation */
-         if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
-           {
-
-             if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
-                 options.stackAuto == 0 &&
-                 (!(options.model == MODEL_FLAT24)) )
-               {
-               }
-             else
-               {
-                 opl = newiTempOperand (args->type, 0);
-                 sym->reqv = opl;
-                 sym->reqv->key = sym->key;
-                 OP_SYMBOL (sym->reqv)->key = sym->key;
-                 OP_SYMBOL (sym->reqv)->isreqv = 1;
-                 OP_SYMBOL (sym->reqv)->islocal = 0;
-                 SPIL_LOC (sym->reqv) = sym;
-               }
-           }
-
-         ic = newiCode (RECEIVE, NULL, NULL);    
-         ic->argreg = SPEC_ARGREG(args->etype);
-         if (first) {
-             currFunc->recvSize = getSize (sym->type);
-             first = 0;
-         }
-         IC_RESULT (ic) = opr;
-         ADDTOCHAIN (ic);
-       }
+        {
+          operand *opr = operandFromValue (args);
+          operand *opl;
+          symbol *sym = OP_SYMBOL (opr);
+          iCode *ic;
+
+          /* we will use it after all optimizations
+             and before liveRange calculation */
+          if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
+            {
+
+              if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
+                  options.stackAuto == 0 &&
+                  (!(options.model == MODEL_FLAT24)) )
+                {
+                }
+              else
+                {
+                  opl = newiTempOperand (args->type, 0);
+                  sym->reqv = opl;
+                  sym->reqv->key = sym->key;
+                  OP_SYMBOL (sym->reqv)->key = sym->key;
+                  OP_SYMBOL (sym->reqv)->isreqv = 1;
+                  OP_SYMBOL (sym->reqv)->islocal = 0;
+                  SPIL_LOC (sym->reqv) = sym;
+                }
+            }
+
+          ic = newiCode (RECEIVE, func, NULL);
+          ic->argreg = SPEC_ARGREG(args->etype);
+          if (ic->argreg == 1) {
+              currFunc->recvSize = getSize (sym->type);
+          }
+          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);
+        }
 
       args = args->next;
     }
@@ -3071,12 +3549,13 @@ geniCodeReceive (value * args)
 /*-----------------------------------------------------------------*/
 /* geniCodeFunctionBody - create the function body                 */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeFunctionBody (ast * tree,int lvl)
 {
   iCode *ic;
   operand *func;
   sym_link *fetype;
+  char *savefilename;
   int savelineno;
 
   /* reset the auto generation */
@@ -3088,21 +3567,26 @@ geniCodeFunctionBody (ast * tree,int lvl)
   func = ast2iCode (tree->left,lvl+1);
   fetype = getSpec (operandType (func));
 
+  savefilename = filename;
   savelineno = lineno;
+  filename = OP_SYMBOL (func)->fileDef;
   lineno = OP_SYMBOL (func)->lineDef;
   /* create an entry label */
   geniCodeLabel (entryLabel);
+  filename = savefilename;
   lineno = savelineno;
 
   /* create a proc icode */
   ic = newiCode (FUNCTION, func, NULL);
-  lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
+  filename = ic->filename = OP_SYMBOL (func)->fileDef;
+  lineno = ic->lineno = OP_SYMBOL (func)->lineDef;
+  ic->tree = tree;
 
   ADDTOCHAIN (ic);
 
   /* for all parameters that are passed
      on registers add a "receive" */
-  geniCodeReceive (tree->values.args);
+  geniCodeReceive (tree->values.args, func);
 
   /* generate code for the body */
   ast2iCode (tree->right,lvl+1);
@@ -3112,6 +3596,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
 
   /* now generate the end proc */
   ic = newiCode (ENDFUNCTION, func, NULL);
+  ic->tree = tree;
   ADDTOCHAIN (ic);
   return;
 }
@@ -3119,7 +3604,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
 /*-----------------------------------------------------------------*/
 /* geniCodeReturn - gen icode for 'return' statement               */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeReturn (operand * op)
 {
   iCode *ic;
@@ -3135,7 +3620,7 @@ geniCodeReturn (operand * op)
 /*-----------------------------------------------------------------*/
 /* geniCodeIfx - generates code for extended if statement          */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeIfx (ast * tree,int lvl)
 {
   iCode *ic;
@@ -3153,37 +3638,35 @@ geniCodeIfx (ast * tree,int lvl)
   if (IS_LITERAL (cetype))
     {
       if (floatFromVal (condition->operand.valOperand))
-       {
-         if (tree->trueLabel)
-           geniCodeGoto (tree->trueLabel);
-         else
-           assert (0);
-       }
+        {
+          if (tree->trueLabel)
+            geniCodeGoto (tree->trueLabel);
+          else
+            assert (0);
+        }
       else
-       {
-         if (tree->falseLabel)
-           geniCodeGoto (tree->falseLabel);
-         else
-           assert (0);
-       }
+        {
+          if (tree->falseLabel)
+            geniCodeGoto (tree->falseLabel);
+        }
       goto exit;
     }
 
   if (tree->trueLabel)
     {
       ic = newiCodeCondition (condition,
-                             tree->trueLabel,
-                             NULL);
+                              tree->trueLabel,
+                              NULL);
       ADDTOCHAIN (ic);
 
       if (tree->falseLabel)
-       geniCodeGoto (tree->falseLabel);
+        geniCodeGoto (tree->falseLabel);
     }
   else
     {
       ic = newiCodeCondition (condition,
-                             NULL,
-                             tree->falseLabel);
+                              NULL,
+                              tree->falseLabel);
       ADDTOCHAIN (ic);
     }
 
@@ -3194,15 +3677,22 @@ 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;
   symbol *falseLabel;
   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;
@@ -3210,66 +3700,131 @@ 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) ulFromVal (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) ulFromVal (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 ((!optimize.noJTabBoundary && 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) ulFromVal (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) ulFromVal (vch);
+        }
+      else
+        {
+          /* Implicit case: use the default label. */
+          addSet (&labels, falseLabel);
+        }
+    }
+
   /* 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)))
-       {
-         boundary = geniCodeLogic (cond, operandFromLit (min), '<');
-         ic = newiCodeCondition (boundary, falseLabel, NULL);
-         ADDTOCHAIN (ic);
-       }
+      if (!(min == 0 && IS_UNSIGNED (cetype)))
+        {
+          boundary = geniCodeLogic (cond, operandFromLit (min), '<', NULL);
+          ic = newiCodeCondition (boundary, falseLabel, NULL);
+          ADDTOCHAIN (ic);
+        }
 
       /* now for upper bounds */
-      boundary = geniCodeLogic (cond, operandFromLit (max), '>');
+      boundary = geniCodeLogic (cond, operandFromLit (max), '>', NULL);
       ic = newiCodeCondition (boundary, falseLabel, NULL);
       ADDTOCHAIN (ic);
     }
@@ -3277,8 +3832,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 */
@@ -3300,21 +3856,60 @@ geniCodeSwitch (ast * tree,int lvl)
   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) ulFromVal (cond->operand.valOperand);
+      while (caseVals)
+        {
+          caseVal = (int) ulFromVal (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 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 */
+    goto jumpTable;             /* no need for the comparison */
 
   /* for the cases defined do */
   while (caseVals)
     {
 
       operand *compare = geniCodeLogic (cond,
-                                       operandFromValue (caseVals),
-                                       EQ_OP);
+                                        operandFromValue (caseVals),
+                                        EQ_OP, NULL);
 
       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
-              tree->values.switchVals.swNum,
-              (int) floatFromVal (caseVals));
+               tree->values.switchVals.swNum,
+               (int) ulFromVal (caseVals));
       trueLabel = newiTempLabel (buffer);
 
       ic = newiCodeCondition (compare, trueLabel, NULL);
@@ -3323,15 +3918,15 @@ geniCodeSwitch (ast * tree,int lvl)
     }
 
 
-
+defaultOrBreak:
   /* if default is present then goto break else break */
   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);
@@ -3344,7 +3939,7 @@ jumpTable:
 /*-----------------------------------------------------------------*/
 /* geniCodeInline - intermediate code for inline assembler         */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeInline (ast * tree)
 {
   iCode *ic;
@@ -3357,7 +3952,7 @@ geniCodeInline (ast * tree)
 /*-----------------------------------------------------------------*/
 /* geniCodeArrayInit - intermediate code for array initializer     */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeArrayInit (ast * tree, operand *array)
 {
   iCode *ic;
@@ -3375,6 +3970,46 @@ 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;
+  sym_link *type;
+
+  if (!options.stackAuto && !TARGET_IS_HC08)
+    {
+      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 & 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);
+}
+
 /*-----------------------------------------------------------------*/
 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
 /* particular case. Ie : assigning or dereferencing array or ptr   */
@@ -3408,7 +4043,7 @@ void delLvaluereq()
   if(lpItem) Safe_free(lpItem);
 }
 /*-----------------------------------------------------------------*/
-/* clearLvaluereq - clear lvalreq flag                            */
+/* clearLvaluereq - clear lvalreq flag                             */
 /*-----------------------------------------------------------------*/
 void clearLvaluereq()
 {
@@ -3417,7 +4052,7 @@ void clearLvaluereq()
   if(lpItem) lpItem->req = 0;
 }
 /*-----------------------------------------------------------------*/
-/* getLvaluereq - get the last lvalreq level                      */
+/* getLvaluereq - get the last lvalreq level                       */
 /*-----------------------------------------------------------------*/
 int getLvaluereqLvl()
 {
@@ -3427,7 +4062,7 @@ int getLvaluereqLvl()
   return 0;
 }
 /*-----------------------------------------------------------------*/
-/* isLvaluereq - is lvalreq valid for this level ?                */
+/* isLvaluereq - is lvalreq valid for this level ?                 */
 /*-----------------------------------------------------------------*/
 int isLvaluereq(int lvl)
 {
@@ -3457,6 +4092,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);
@@ -3469,8 +4106,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;
     }
 
@@ -3479,11 +4122,14 @@ 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 &&
       tree->opval.op != FUNCTION &&
-      tree->opval.op != INLINEASM)
+      tree->opval.op != INLINEASM &&
+      tree->opval.op != CRITICAL)
     {
 
         if (IS_ASSIGN_OP (tree->opval.op) ||
@@ -3499,22 +4145,22 @@ ast2iCode (ast * tree,int lvl)
             left = operandFromAst (tree->left,lvl);
             delLvaluereq();
             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
-             left = geniCodeRValue (left, TRUE);
+              left = geniCodeRValue (left, TRUE);
           }
         else
           {
-           left = operandFromAst (tree->left,lvl);
+            left = operandFromAst (tree->left,lvl);
           }
         if (tree->opval.op == INC_OP ||
-           tree->opval.op == DEC_OP)
+            tree->opval.op == DEC_OP)
           {
-           addLvaluereq(lvl);
-           right = operandFromAst (tree->right,lvl);
-           delLvaluereq();
+            addLvaluereq(lvl);
+            right = operandFromAst (tree->right,lvl);
+            delLvaluereq();
           }
         else
           {
-           right = operandFromAst (tree->right,lvl);
+            right = operandFromAst (tree->right,lvl);
           }
       }
 
@@ -3523,153 +4169,188 @@ ast2iCode (ast * tree,int lvl)
   switch (tree->opval.op)
     {
 
-    case '[':                  /* array operation */
+    case '[':                   /* array operation */
       {
-       //sym_link *ltype = operandType (left);
-       //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
-       left = geniCodeRValue (left, FALSE);
-       right = geniCodeRValue (right, TRUE);
+        //sym_link *ltype = operandType (left);
+        //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+        left = geniCodeRValue (left, FALSE);
+        right = geniCodeRValue (right, TRUE);
       }
 
       return geniCodeArray (left, right,lvl);
 
-    case '.':                  /* structure dereference */
+    case '.':                   /* structure dereference */
       if (IS_PTR (operandType (left)))
-       left = geniCodeRValue (left, TRUE);
+        left = geniCodeRValue (left, TRUE);
       else
-       left = geniCodeRValue (left, FALSE);
+        left = geniCodeRValue (left, FALSE);
 
       return geniCodeStruct (left, right, tree->lvalue);
 
-    case PTR_OP:               /* structure pointer dereference */
+    case PTR_OP:                /* structure pointer dereference */
       {
-       sym_link *pType;
-       pType = operandType (left);
-       left = geniCodeRValue (left, TRUE);
+        sym_link *pType;
+        pType = operandType (left);
+        left = geniCodeRValue (left, TRUE);
 
-       setOClass (pType, getSpec (operandType (left)));
+        setOClass (pType, getSpec (operandType (left)));
       }
 
       return geniCodeStruct (left, right, tree->lvalue);
 
-    case INC_OP:               /* increment operator */
+    case INC_OP:                /* increment operator */
       if (left)
-       return geniCodePostInc (left);
+        return geniCodePostInc (left);
       else
-       return geniCodePreInc (right);
+        return geniCodePreInc (right, tree->lvalue);
 
-    case DEC_OP:               /* decrement operator */
+    case DEC_OP:                /* decrement operator */
       if (left)
-       return geniCodePostDec (left);
+        return geniCodePostDec (left);
       else
-       return geniCodePreDec (right);
+        return geniCodePreDec (right, tree->lvalue);
 
-    case '&':                  /* bitwise and or address of operator */
+    case '&':                   /* bitwise and or address of operator */
       if (right)
-       {                       /* this is a bitwise operator   */
-         left = geniCodeRValue (left, FALSE);
-         right = geniCodeRValue (right, FALSE);
-         return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
-       }
+        {                       /* this is a bitwise operator   */
+          left = geniCodeRValue (left, FALSE);
+          right = geniCodeRValue (right, FALSE);
+          return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
+        }
       else
-       return geniCodeAddressOf (left);
+        return geniCodeAddressOf (left);
 
-    case '|':                  /* bitwise or & xor */
+    case '|':                   /* bitwise or & xor */
     case '^':
       return geniCodeBitwise (geniCodeRValue (left, FALSE),
-                             geniCodeRValue (right, FALSE),
-                             tree->opval.op,
-                             tree->ftype);
+                              geniCodeRValue (right, FALSE),
+                              tree->opval.op,
+                              tree->ftype);
 
     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));
+        return geniCodeMultiply (geniCodeRValue (left, FALSE),
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype));
       else
-       return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
+        return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
     case '-':
       if (right)
-       return geniCodeSubtract (geniCodeRValue (left, FALSE),
-                                geniCodeRValue (right, FALSE));
+        return geniCodeSubtract (geniCodeRValue (left, FALSE),
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype));
       else
-       return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
+        return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
 
     case '+':
       if (right)
-       return geniCodeAdd (geniCodeRValue (left, FALSE),
-                           geniCodeRValue (right, FALSE),lvl);
+        return geniCodeAdd (geniCodeRValue (left, FALSE),
+                            geniCodeRValue (right, FALSE),
+                            getResultTypeFromType (tree->ftype),
+                            lvl);
       else
-       return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
+        return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
 
     case LEFT_OP:
       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
-                               geniCodeRValue (right, FALSE));
+                                geniCodeRValue (right, FALSE),
+                                getResultTypeFromType (tree->ftype));
 
     case RIGHT_OP:
       return geniCodeRightShift (geniCodeRValue (left, FALSE),
-                                geniCodeRValue (right, FALSE));
-    case CAST: 
+                                 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;
+        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);
+                           geniCodeRValue (right, FALSE), FALSE);
 #endif
 
     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);
-       setOperandType (op, UCHARTYPE);
-       return op;
+        operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
+        if (!IS_BIT (operandType (op)))
+          setOperandType (op, UCHARTYPE);
+        return op;
       }
+    case GETABIT:
+      {
+        operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
+                                      geniCodeRValue (right, FALSE),
+                                      tree->opval.op);
+        if (!IS_BIT (operandType (op)))
+          setOperandType (op, UCHARTYPE);
+        return op;
+      }
+    case GETBYTE:
+      {
+        operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
+                                      geniCodeRValue (right, FALSE),
+                                      tree->opval.op);
+        setOperandType (op, UCHARTYPE);
+        return op;
+      }
+    case GETWORD:
+      {
+        operand *op = geniCodeBinary (geniCodeRValue (left, FALSE),
+                                      geniCodeRValue (right, FALSE),
+                                      tree->opval.op);
+        setOperandType (op, UINTTYPE);
+        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 have 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, tree);
       }
     case '?':
       return geniCodeConditional (tree,lvl);
@@ -3679,113 +4360,125 @@ ast2iCode (ast * tree,int lvl)
 
     case '=':
       {
-       sym_link *rtype = operandType (right);
-       sym_link *ltype = operandType (left);
-       if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && compareType (rtype->next, ltype) == 1)
-         right = geniCodeRValue (right, TRUE);
-       else
-         right = geniCodeRValue (right, FALSE);
-
-       geniCodeAssign (left, right, 0);
-       return right;
+        sym_link *rtype = operandType (right);
+        sym_link *ltype = operandType (left);
+        if (IS_PTR (rtype) && IS_ITEMP (right)
+            && right->isaddr && compareType (rtype->next, ltype) == 1)
+          right = geniCodeRValue (right, TRUE);
+        else
+          right = geniCodeRValue (right, FALSE);
+
+        return geniCodeAssign (left, right, 0, 1);
       }
     case MUL_ASSIGN:
       return
-       geniCodeAssign (left,
-               geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
-                                                 FALSE),
-                                 geniCodeRValue (right, FALSE),FALSE), 0);
+        geniCodeAssign (left,
+                geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  getResultTypeFromType (tree->ftype)),
+                        0, 1);
 
     case DIV_ASSIGN:
       return
-       geniCodeAssign (left,
-               geniCodeDivision (geniCodeRValue (operandFromOperand (left),
-                                                 FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+        geniCodeAssign (left,
+                geniCodeDivision (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  getResultTypeFromType (tree->ftype)),
+                        0, 1);
     case MOD_ASSIGN:
       return
-       geniCodeAssign (left,
-                geniCodeModulus (geniCodeRValue (operandFromOperand (left),
-                                                 FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+        geniCodeAssign (left,
+                 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  getResultTypeFromType (tree->ftype)),
+                        0, 1);
     case ADD_ASSIGN:
       {
-       sym_link *rtype = operandType (right);
-       sym_link *ltype = operandType (left);
-       if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && compareType (rtype->next, ltype) == 1)
-         right = geniCodeRValue (right, TRUE);
-       else
-         right = geniCodeRValue (right, FALSE);
-
-
-       return geniCodeAssign (left,
-                    geniCodeAdd (geniCodeRValue (operandFromOperand (left),
-                                                 FALSE),
-                                 right,lvl), 0);
+        sym_link *rtype = operandType (right);
+        sym_link *ltype = operandType (left);
+        if (IS_PTR (rtype) && IS_ITEMP (right)
+            && right->isaddr && compareType (rtype->next, ltype) == 1)
+          right = geniCodeRValue (right, TRUE);
+        else
+          right = geniCodeRValue (right, FALSE);
+
+
+        return geniCodeAssign (left,
+                     geniCodeAdd (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  right,
+                                  getResultTypeFromType (tree->ftype),
+                                  lvl),
+                               0, 1);
       }
     case SUB_ASSIGN:
       {
-       sym_link *rtype = operandType (right);
-       sym_link *ltype = operandType (left);
-       if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && compareType (rtype->next, ltype) == 1)
-         {
-           right = geniCodeRValue (right, TRUE);
-         }
-       else
-         {
-           right = geniCodeRValue (right, FALSE);
-         }
-       return
-         geniCodeAssign (left,
-               geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
-                                                 FALSE),
-                                 right), 0);
+        sym_link *rtype = operandType (right);
+        sym_link *ltype = operandType (left);
+        if (IS_PTR (rtype) && IS_ITEMP (right)
+            && right->isaddr && compareType (rtype->next, ltype) == 1)
+          {
+            right = geniCodeRValue (right, TRUE);
+          }
+        else
+          {
+            right = geniCodeRValue (right, FALSE);
+          }
+        return
+          geniCodeAssign (left,
+                geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  right,
+                                  getResultTypeFromType (tree->ftype)),
+                          0, 1);
       }
     case LEFT_ASSIGN:
       return
-       geniCodeAssign (left,
-               geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
-                                                  ,FALSE),
-                                  geniCodeRValue (right, FALSE)), 0);
+        geniCodeAssign (left,
+                geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
+                                                   ,FALSE),
+                                   geniCodeRValue (right, FALSE),
+                                   getResultTypeFromType (tree->ftype)),
+                        0, 1);
     case RIGHT_ASSIGN:
       return
-       geniCodeAssign (left,
-              geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
-                                                  ,FALSE),
-                                  geniCodeRValue (right, FALSE)), 0);
+        geniCodeAssign (left,
+               geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
+                                                   ,FALSE),
+                                   geniCodeRValue (right, FALSE)), 0, 1);
     case AND_ASSIGN:
       return
-       geniCodeAssign (left,
-                geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
-                                                 FALSE),
-                                 geniCodeRValue (right, FALSE),
-                                 BITWISEAND,
-                                 operandType (left)), 0);
+        geniCodeAssign (left,
+                 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  BITWISEAND,
+                                  operandType (left)), 0, 1);
     case XOR_ASSIGN:
       return
-       geniCodeAssign (left,
-                geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
-                                                 FALSE),
-                                 geniCodeRValue (right, FALSE),
-                                 '^',
-                                 operandType (left)), 0);
+        geniCodeAssign (left,
+                 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  '^',
+                                  operandType (left)), 0, 1);
     case OR_ASSIGN:
       return
-       geniCodeAssign (left,
-                 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
-                                                  ,FALSE),
-                                  geniCodeRValue (right, FALSE),
-                                  '|',
-                                  operandType (left)), 0);
+        geniCodeAssign (left,
+                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
+                                                   ,FALSE),
+                                   geniCodeRValue (right, FALSE),
+                                   '|',
+                                   operandType (left)), 0, 1);
     case ',':
       return geniCodeRValue (right, FALSE);
 
     case CALL:
       return geniCodeCall (ast2iCode (tree->left,lvl+1),
-                          tree->right,lvl);
+                           tree->right,lvl);
     case LABEL:
       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
       return ast2iCode (tree->right,lvl+1);
@@ -3813,10 +4506,13 @@ ast2iCode (ast * tree,int lvl)
     case INLINEASM:
       geniCodeInline (tree);
       return NULL;
-       
+
     case ARRAYINIT:
-       geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
-       return NULL;
+        geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
+        return NULL;
+
+    case CRITICAL:
+        geniCodeCritical (tree, lvl);
     }
 
   return NULL;
@@ -3835,7 +4531,7 @@ reverseiCChain ()
     {
       loop->next = prev;
       if (prev)
-       prev->prev = loop;
+        prev->prev = loop;
       prev = loop;
     }
 
@@ -3863,26 +4559,26 @@ static const char *opTypeToStr(OPTYPE op)
       case VALUE: return "value";
       case TYPE: return "type";
     }
-    return "undefined type";    
+    return "undefined type";
 }
 
 
-operand *validateOpType(operand        *op, 
-                       const char      *macro,
-                       const char      *args,
-                       OPTYPE          type,
-                       const char      *file, 
-                       unsigned        line)
-{    
+operand *validateOpType(operand         *op,
+                        const char      *macro,
+                        const char      *args,
+                        OPTYPE          type,
+                        const char      *file,
+                        unsigned        line)
+{
     if (op && op->type == type)
     {
-       return op;
+        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);
+    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(EXIT_FAILURE);
     return op; // never reached, makes compiler happy.
 }