* configure.in, configure: have device/lib/pic configured
[fw/sdcc] / src / SDCCicode.c
index 03a7c45688c17865cf98f1170c04130a0cb7a507..ee4783cd8978a02ffd7092349b093201d450e4f6 100644 (file)
 /*-------------------------------------------------------------------------
 
 /*-------------------------------------------------------------------------
 
-  SDCCicode.c - intermediate code generation etc.                  
+  SDCCicode.c - intermediate code generation etc.
                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   
+
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
 #include "common.h"
 -------------------------------------------------------------------------*/
 
 #include "common.h"
+#include "newalloc.h"
+#include "math.h"
 
 /*-----------------------------------------------------------------*/
 /* global variables       */
 
 
 /*-----------------------------------------------------------------*/
 /* global variables       */
 
-set *iCodeChain = NULL ;
+set *iCodeChain = NULL;
 int iTempNum = 0;
 int iTempLblNum = 0;
 int iTempNum = 0;
 int iTempLblNum = 0;
-int operandKey = 0 ;
+int operandKey = 0;
 int iCodeKey = 0;
 int iCodeKey = 0;
-char *filename ;
-int lineno ;
+char *filename;
+int lineno;
 int block;
 int scopeLevel;
 int block;
 int scopeLevel;
-int lvaluereq;
+int seqPoint;
 
 
-extern int labelKey ;
+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 */
 /*-----------------------------------------------------------------*/
 /* forward definition of some functions */
-operand *geniCodeDivision (operand *,operand *);
-operand *geniCodeAssign   (operand *,operand *,int);
-operand *geniCodeArray (operand *,operand *);
-operand *geniCodeArray2Ptr (operand *);
-operand *geniCodeRValue (operand *, bool );
-operand *geniCodeDerefPtr (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 (FILE *of, iCode *ic, char *s)
-/* forward definition of print functions */
-PRINTFUNC(picGetValueAtAddr);
-PRINTFUNC(picSetValueAtAddr);
-PRINTFUNC(picAddrOf);
-PRINTFUNC(picGeneric);
-PRINTFUNC(picGenericOne);
-PRINTFUNC(picCast);
-PRINTFUNC(picAssign);
-PRINTFUNC(picLabel);
-PRINTFUNC(picGoto);
-PRINTFUNC(picIfx);
-PRINTFUNC(picJumpTable);
-PRINTFUNC(picInline);
-PRINTFUNC(picReceive);
-
-iCodeTable codeTable[] = {
-  { '!'                 ,  "not", picGenericOne    , NULL },
-  { '~'                 ,  "~"  , picGenericOne    , NULL },
-  { RRC                 ,  "rrc", picGenericOne    , NULL },
-  { RLC                 ,  "rlc", picGenericOne    , NULL },
-  { GETHBIT             ,"ghbit", picGenericOne    , NULL },
-  { UNARYMINUS          ,  "-"  , picGenericOne    , NULL },
-  { IPUSH               ,  "push",picGenericOne    , NULL },
-  { IPOP                ,  "pop", picGenericOne    , NULL },
-  { CALL                ,  "call",picGenericOne    , NULL },
-  { PCALL               , "pcall",picGenericOne    , NULL }, 
-  { FUNCTION            , "proc", picGenericOne    , NULL },
-  { ENDFUNCTION         ,"eproc", picGenericOne    , NULL },
-  { RETURN              ,  "ret", picGenericOne    , NULL },
-  { '+'                 ,  "+"  , picGeneric       , NULL },
-  { '-'                 ,  "-"  , picGeneric       , NULL },
-  { '*'                 ,  "*"  , picGeneric       , NULL },
-  { '/'                 ,  "/"  , picGeneric       , NULL },
-  { '%'                 ,  "%"  , picGeneric       , NULL },
-  { '>'                 ,  ">"  , picGeneric       , NULL },
-  { '<'                 ,  "<"  , picGeneric       , NULL },
-  { LE_OP               ,  "<=" , picGeneric       , NULL },
-  { GE_OP               ,  ">=" , picGeneric       , NULL },
-  { EQ_OP               ,  "==" , picGeneric       , NULL },
-  { NE_OP               ,  "!=" , picGeneric       , NULL },  
-  { AND_OP              ,  "&&" , picGeneric       , NULL },
-  { OR_OP               ,  "||" , picGeneric       , NULL },
-  { '^'                 ,  "^"  , picGeneric       , NULL },
-  { '|'                 ,  "|"  , picGeneric       , NULL },
-  { BITWISEAND          ,  "&"  , picGeneric       , NULL },
-  { LEFT_OP             ,  "<<" , picGeneric       , NULL },
-  { RIGHT_OP            ,  ">>" , picGeneric       , NULL },
-  { GET_VALUE_AT_ADDRESS,  "@"  , picGetValueAtAddr, NULL },
-  { ADDRESS_OF          ,  "&"  , picAddrOf        , NULL },
-  { CAST                ,  "<>" , picCast          , NULL },
-  { '='                 ,  ":=" , picAssign        , NULL },
-  { LABEL               ,  ""   , picLabel         , NULL },
-  { GOTO                ,  ""   , picGoto          , NULL },
-  { JUMPTABLE           ,"jtab" , picJumpTable     , NULL },
-  { IFX                 ,  "if" , picIfx           , NULL },
-  { INLINEASM           , ""    , picInline        , NULL },
-  { RECEIVE             , "recv", picReceive       , NULL },
-  { SEND                , "send", picGenericOne    , NULL }
+/* forward definition of ic print functions */
+PRINTFUNC (picGetValueAtAddr);
+PRINTFUNC (picSetValueAtAddr);
+PRINTFUNC (picAddrOf);
+PRINTFUNC (picGeneric);
+PRINTFUNC (picGenericOne);
+PRINTFUNC (picCast);
+PRINTFUNC (picAssign);
+PRINTFUNC (picLabel);
+PRINTFUNC (picGoto);
+PRINTFUNC (picIfx);
+PRINTFUNC (picJumpTable);
+PRINTFUNC (picInline);
+PRINTFUNC (picReceive);
+PRINTFUNC (picDummyRead);
+PRINTFUNC (picCritical);
+PRINTFUNC (picEndCritical);
+
+iCodeTable codeTable[] =
+{
+  {'!', "not", picGenericOne, NULL},
+  {'~', "~", picGenericOne, NULL},
+  {RRC, "rrc", picGenericOne, NULL},
+  {RLC, "rlc", picGenericOne, NULL},
+  {GETHBIT, "ghbit", picGenericOne, NULL},
+  {UNARYMINUS, "-", picGenericOne, NULL},
+  {IPUSH, "push", picGenericOne, NULL},
+  {IPOP, "pop", picGenericOne, NULL},
+  {CALL, "call", picGenericOne, NULL},
+  {PCALL, "pcall", picGenericOne, NULL},
+  {FUNCTION, "proc", picGenericOne, NULL},
+  {ENDFUNCTION, "eproc", picGenericOne, NULL},
+  {RETURN, "ret", picGenericOne, NULL},
+  {'+', "+", picGeneric, NULL},
+  {'-', "-", picGeneric, NULL},
+  {'*', "*", picGeneric, NULL},
+  {'/', "/", picGeneric, NULL},
+  {'%', "%", picGeneric, NULL},
+  {'>', ">", picGeneric, NULL},
+  {'<', "<", picGeneric, NULL},
+  {LE_OP, "<=", picGeneric, NULL},
+  {GE_OP, ">=", picGeneric, NULL},
+  {EQ_OP, "==", picGeneric, NULL},
+  {NE_OP, "!=", picGeneric, NULL},
+  {AND_OP, "&&", picGeneric, NULL},
+  {OR_OP, "||", picGeneric, NULL},
+  {'^', "^", picGeneric, NULL},
+  {'|', "|", picGeneric, NULL},
+  {BITWISEAND, "&", picGeneric, NULL},
+  {LEFT_OP, "<<", picGeneric, NULL},
+  {RIGHT_OP, ">>", picGeneric, NULL},
+  {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
+  {ADDRESS_OF, "&", picAddrOf, NULL},
+  {CAST, "<>", picCast, NULL},
+  {'=', ":=", picAssign, NULL},
+  {LABEL, "", picLabel, NULL},
+  {GOTO, "", picGoto, NULL},
+  {JUMPTABLE, "jtab", picJumpTable, NULL},
+  {IFX, "if", picIfx, NULL},
+  {INLINEASM, "", picInline, NULL},
+  {RECEIVE, "recv", picReceive, NULL},
+  {SEND, "send", picGenericOne, NULL},
+  {ARRAYINIT, "arrayInit", picGenericOne, NULL},
+  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
+  {CRITICAL, "critical_start", picCritical, NULL},
+  {ENDCRITICAL, "critical_end", picEndCritical, NULL},
+  {SWAP, "swap", picGenericOne, NULL}
 };
 
 };
 
+/*-----------------------------------------------------------------*/
+/* checkConstantRange: check a constant against the type           */
+/*-----------------------------------------------------------------*/
+
+
+/*   pedantic=0: allmost anything is allowed as long as the absolute
+       value is within the bit range of the type, and -1 is treated as
+       0xf..f for unsigned types (e.g. in assign)
+     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 (IS_LONG(val->type)) {
+    if (IS_UNSIGNED(val->type)) {
+      v=SPEC_CVAL(val->type).v_ulong;
+    } else {
+      v=SPEC_CVAL(val->type).v_long;
+    }
+  } else {
+    if (IS_UNSIGNED(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 (IS_FLOAT(ltype)) {
+    // anything will do
+    return;
+  }
+
+  if (IS_FIXED(ltype)) {
+    // anything will do
+    return;
+  }
+
+  if (!IS_UNSIGNED(val->type) && v<0) {
+    negative=1;
+    if (IS_UNSIGNED(ltype) && (pedantic>1)) {
+      warnings++;
+    }
+    v=-v;
+  }
+
+  // if very pedantic: "char c=200" is not allowed
+  if (pedantic>1 && !IS_UNSIGNED(ltype)) {
+    max = max/2 + negative;
+  }
+
+  if (v >= max) {
+    warnings++;
+  }
+
+#if 0 // temporary disabled, leaving the warning as a reminder
+  if (warnings) {
+    SNPRINTF (message, sizeof(message), "for %s %s in %s",
+             IS_UNSIGNED(ltype) ? "unsigned" : "signed",
+             nounName(ltype), msg);
+    werror (W_CONST_RANGE, message);
+
+    if (pedantic>1)
+      fatalError++;
+  }
+#endif
+}
 
 /*-----------------------------------------------------------------*/
 /* operandName - returns the name of the operand                   */
 /*-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------*/
 /* operandName - returns the name of the operand                   */
 /*-----------------------------------------------------------------*/
-int printOperand (operand *op, FILE *file)
+int
+printOperand (operand * op, FILE * file)
 {
 {
-    link *opetype;
-    int pnl = 0;
+  sym_link *opetype;
+  int pnl = 0;
 
 
-    if (!op)
-       return 1;
+  if (!op)
+    return 1;
 
 
-    if (!file) {
-       file = stdout;
-       pnl = 1;
+  if (!file)
+    {
+      file = stdout;
+      pnl = 1;
     }
     }
-    switch (op->type) {
-       
+  switch (op->type)
+    {
+
     case VALUE:
     case VALUE:
-       opetype = getSpec (operandType(op));
-       if (SPEC_NOUN(opetype) == V_FLOAT)
-           fprintf (file,"%g {", SPEC_CVAL(opetype).v_float);
-       else 
-           fprintf (file,"0x%x {",(int) floatFromVal(op->operand.valOperand));
-       printTypeChain(operandType(op),file);
-       fprintf(file,"}");
-       break;
-       
-    case SYMBOL :
+      opetype = getSpec (operandType (op));
+      if (IS_FLOAT (opetype))
+        fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
+      if (IS_FIXED16X16 (opetype))
+        fprintf (file, "%g {", doubleFromFixed16x16(SPEC_CVAL (opetype).v_fixed16x16));
+      else
+        fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
+      printTypeChain (operandType (op), file);
+      fprintf (file, "}");
+      break;
+
+    case SYMBOL:
 #define REGA 1
 #define REGA 1
-#ifdef REGA    
-       fprintf (file,"%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%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
-                );
-       {
-           fprintf(file,"{"); printTypeChain(operandType(op),file); 
-           if (SPIL_LOC(op) && IS_ITEMP(op))
-               fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
-           fprintf(file,"}");
-
-       }
-       
-       /* if assigned to registers */
-       if (OP_SYMBOL(op)->nRegs) {
-           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 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
-       break ;
-       
+//#if REGA      /* { */
+    if(REGA && !getenv("PRINT_SHORT_OPERANDS")) {
+      fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d a2p%d re%d rm%d nos%d ru%d dp%d}",           /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}"  , */
+               (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
+               op->key,
+               OP_LIVEFROM (op), OP_LIVETO (op),
+               OP_SYMBOL (op)->stack,
+               op->isaddr, op->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, "}");
+
+      }
+
+      /* 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         /* } else { */
+    } else {
+      /* (getenv("PRINT_SHORT_OPERANDS") != NULL) */
+      fprintf (file, "%s ", (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
+
+      if(getenv("PRINT_SHORT_OPERANDS")[0] < '1')
+        {
+          fprintf (file, "[lr%d:%d so:%d]",
+               OP_LIVEFROM (op), OP_LIVETO (op),
+               OP_SYMBOL (op)->stack);
+        }
+
+      if(getenv("PRINT_SHORT_OPERANDS")[0] < '2')
+        {
+          fprintf (file, "{");
+          printTypeChain (operandType (op), file);
+          if (SPIL_LOC (op) && IS_ITEMP (op))
+              fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
+          fprintf (file, "}");
+        }
+
+      /* if assigned to registers */
+      if (OP_SYMBOL (op)->nRegs)
+        {
+          if (OP_SYMBOL (op)->isspilt)
+            {
+              if (!OP_SYMBOL (op)->remat)
+                if (OP_SYMBOL (op)->usl.spillLoc)
+                  fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
+                                       OP_SYMBOL (op)->usl.spillLoc->rname :
+                                       OP_SYMBOL (op)->usl.spillLoc->name));
+                else
+                  fprintf (file, "[err]");
+              else
+                fprintf (file, "[remat]");
+            }
+          else
+            {
+              int i;
+              fprintf (file, "[");
+              for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
+                fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
+              fprintf (file, "]");
+            }
+        }
+//#endif                /* } */
+    }
+      break;
+
     case TYPE:
     case TYPE:
-       fprintf(file,"(");
-       printTypeChain(op->operand.typeOperand,file);
-       fprintf(file,")");
-       break;
-    }
-    
-    if (pnl)
-       fprintf(file,"\n");
-    return 0;
+      fprintf (file, "(");
+      printTypeChain (op->operand.typeOperand, file);
+      fprintf (file, ")");
+      break;
+    }
+
+  if (pnl)
+    fprintf (file, "\n");
+  return 0;
 }
 
 
 /*-----------------------------------------------------------------*/
 /*                    print functions                              */
 /*-----------------------------------------------------------------*/
 }
 
 
 /*-----------------------------------------------------------------*/
 /*                    print functions                              */
 /*-----------------------------------------------------------------*/
-PRINTFUNC(picGetValueAtAddr)
+PRINTFUNC (picGetValueAtAddr)
 {
 {
-    fprintf(of,"\t");
-    printOperand (IC_RESULT(ic),of);
-    fprintf (of," = ");
-    fprintf (of,"@[");
-    printOperand (IC_LEFT(ic), of);
-    fprintf (of,"]");
-    
-    fprintf(of,"\n");
+  fprintf (of, "\t");
+  printOperand (IC_RESULT (ic), of);
+  fprintf (of, " = ");
+  fprintf (of, "@[");
+  printOperand (IC_LEFT (ic), of);
+  fprintf (of, "]");
+
+  fprintf (of, "\n");
 }
 
 }
 
-PRINTFUNC(picSetValueAtAddr)
+PRINTFUNC (picSetValueAtAddr)
 {
 {
-    fprintf(of,"\t");
-    fprintf(of,"*[");
-    printOperand(IC_LEFT(ic),of);
-    fprintf(of,"] = ");
-    printOperand(IC_RIGHT(ic),of);
-    fprintf (of,"\n");
+  fprintf (of, "\t");
+  fprintf (of, "*[");
+  printOperand (IC_LEFT (ic), of);
+  fprintf (of, "] = ");
+  printOperand (IC_RIGHT (ic), of);
+  fprintf (of, "\n");
 }
 
 }
 
-PRINTFUNC(picAddrOf)
+PRINTFUNC (picAddrOf)
 {
 {
-    fprintf(of,"\t");
-    printOperand(IC_RESULT(ic),of);
-    if (IS_ITEMP(IC_LEFT(ic)))
-       fprintf(of," = ");
-    else
-       fprintf(of," = &[");
-    printOperand(IC_LEFT(ic),of);
-    if (IC_RIGHT(ic)) {
-       if (IS_ITEMP(IC_LEFT(ic)))
-           fprintf(of," offsetAdd ");
-       else
-           fprintf(of," , ");
-       printOperand(IC_RIGHT(ic),of);
+  fprintf (of, "\t");
+  printOperand (IC_RESULT (ic), of);
+  if (IS_ITEMP (IC_LEFT (ic)))
+    fprintf (of, " = ");
+  else
+    fprintf (of, " = &[");
+  printOperand (IC_LEFT (ic), of);
+  if (IC_RIGHT (ic))
+    {
+      if (IS_ITEMP (IC_LEFT (ic)))
+        fprintf (of, " offsetAdd ");
+      else
+        fprintf (of, " , ");
+      printOperand (IC_RIGHT (ic), of);
     }
     }
-    if (IS_ITEMP(IC_LEFT(ic)))
-       fprintf (of,"\n");
-    else
-       fprintf (of,"]\n");
+  if (IS_ITEMP (IC_LEFT (ic)))
+    fprintf (of, "\n");
+  else
+    fprintf (of, "]\n");
 }
 
 }
 
-PRINTFUNC(picJumpTable)
+PRINTFUNC (picJumpTable)
 {
 {
-    symbol *sym;
-
-    fprintf(of,"\t");
-    fprintf(of,"%s\t",s);
-    printOperand(IC_JTCOND(ic),of);
-    fprintf(of,"\n");
-    for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
-         sym = setNextItem(IC_JTLABELS(ic))) 
-       fprintf(of,"\t\t\t%s\n",sym->name);
+  symbol *sym;
+
+  fprintf (of, "\t");
+  fprintf (of, "%s\t", s);
+  printOperand (IC_JTCOND (ic), of);
+  fprintf (of, "\n");
+  for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
+       sym = setNextItem (IC_JTLABELS (ic)))
+    fprintf (of, "\t\t\t%s\n", sym->name);
 }
 
 }
 
-PRINTFUNC(picGeneric)
+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");
+  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");
 }
 
 }
 
-PRINTFUNC(picGenericOne)
+PRINTFUNC (picGenericOne)
 {
 {
-    fprintf(of,"\t");
-    if ( IC_RESULT(ic) ) {
-       printOperand(IC_RESULT(ic),of);
-       fprintf (of," = ");
+  fprintf (of, "\t");
+  if (IC_RESULT (ic))
+    {
+      printOperand (IC_RESULT (ic), of);
+      fprintf (of, " = ");
     }
     }
-    
-    if (IC_LEFT(ic)) {
-       fprintf (of,"%s ",s);
-       printOperand(IC_LEFT(ic),of);     
+
+  if (IC_LEFT (ic))
+    {
+      fprintf (of, "%s ", s);
+      printOperand (IC_LEFT (ic), of);
     }
     }
-    
-    if (! IC_RESULT(ic) && !IC_LEFT(ic))
-       fprintf (of,s);
-    
-    fprintf(of,"\n");
+
+  if (!IC_RESULT (ic) && !IC_LEFT (ic))
+    fprintf (of, s);
+
+  if (ic->op == SEND || ic->op == RECEIVE) {
+      fprintf(of,"{argreg = %d}",ic->argreg);
+  }
+  if (ic->op == IPUSH) {
+      fprintf(of,"{parmPush = %d}",ic->parmPush);
+  }
+  fprintf (of, "\n");
 }
 
 }
 
-PRINTFUNC(picCast)
+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");
+  fprintf (of, "\t");
+  printOperand (IC_RESULT (ic), of);
+  fprintf (of, " = ");
+  printOperand (IC_LEFT (ic), of);
+  printOperand (IC_RIGHT (ic), of);
+  fprintf (of, "\n");
 }
 
 
 }
 
 
-PRINTFUNC(picAssign)
+PRINTFUNC (picAssign)
 {
 {
-    fprintf(of,"\t");
-    
-    if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
-       fprintf(of,"*(");
-    
-    printOperand(IC_RESULT(ic),of);  
-    
-    if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
-       fprintf(of,")");
-    
-    fprintf(of," %s ", s);
-    printOperand (IC_RIGHT(ic),of);
-    
-    fprintf(of,"\n");
+  fprintf (of, "\t");
+
+  if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
+    fprintf (of, "*(");
+
+  printOperand (IC_RESULT (ic), of);
+
+  if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
+    fprintf (of, ")");
+
+  fprintf (of, " %s ", s);
+  printOperand (IC_RIGHT (ic), of);
+
+  fprintf (of, "\n");
 }
 
 }
 
-PRINTFUNC(picLabel)
+PRINTFUNC (picLabel)
 {
 {
-    fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
+  fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
 }
 
 }
 
-PRINTFUNC(picGoto)
+PRINTFUNC (picGoto)
 {
 {
-   fprintf(of,"\t");
-   fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
+  fprintf (of, "\t");
+  fprintf (of, " 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);
-    
-    if ( ! IC_TRUE(ic) ) 
-       fprintf (of," == 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);
-       if (IC_FALSE(ic))
-           fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
+PRINTFUNC (picIfx)
+{
+  fprintf (of, "\t");
+  fprintf (of, "if ");
+  printOperand (IC_COND (ic), of);
+
+  if (!IC_TRUE (ic))
+    fprintf (of, " == 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);
+      if (IC_FALSE (ic))
+        fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
     }
 }
 
     }
 }
 
-PRINTFUNC(picInline)
+PRINTFUNC (picInline)
+{
+  fprintf (of, "%s", IC_INLINE (ic));
+}
+
+PRINTFUNC (picReceive)
+{
+  printOperand (IC_RESULT (ic), of);
+  fprintf (of, " = %s ", s);
+  printOperand (IC_LEFT (ic), of);
+  fprintf (of, "\n");
+}
+
+PRINTFUNC (picDummyRead)
+{
+  fprintf (of, "\t");
+  fprintf (of, "%s ", s);
+  printOperand (IC_RIGHT (ic), of);
+  fprintf (of, "\n");
+}
+
+PRINTFUNC (picCritical)
 {
 {
-    fprintf(of,"%s",IC_INLINE(ic));
+  fprintf (of, "\t");
+  if (IC_RESULT (ic))
+    printOperand (IC_RESULT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, " = %s ", s);
+  fprintf (of, "\n");
 }
 
 }
 
-PRINTFUNC(picReceive)
+PRINTFUNC (picEndCritical)
 {
 {
-    printOperand(IC_RESULT(ic),of);
-    fprintf(of," = %s ",s);
-    printOperand(IC_LEFT(ic),of);
-    fprintf(of,"\n");
+  fprintf (of, "\t");
+  fprintf (of, "%s = ", s);
+  if (IC_RIGHT (ic))
+    printOperand (IC_RIGHT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, "\n");
 }
 
 /*-----------------------------------------------------------------*/
 /* piCode - prints one iCode                                       */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* piCode - prints one iCode                                       */
 /*-----------------------------------------------------------------*/
-int piCode (void *item, FILE *of)
+int
+piCode (void *item, FILE * of)
 {
 {
-    iCode *ic = item;
-    iCodeTable *icTab ;
-    
-    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);
-    return 1;
+  iCode *ic = item;
+  iCodeTable *icTab;
+
+  if (!of)
+    of = stdout;
+
+  icTab = getTableEntry (ic->op);
+  fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
+           ic->filename, ic->lineno,
+           ic->seq, ic->key, ic->depth, ic->supportRtn);
+  icTab->iCodePrint (of, ic, icTab->printName);
+  return 1;
 }
 
 }
 
+void PICC(iCode *ic)
+{
+        printiCChain(ic,stdout);
+}
 /*-----------------------------------------------------------------*/
 /* printiCChain - prints intermediate code for humans              */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* printiCChain - prints intermediate code for humans              */
 /*-----------------------------------------------------------------*/
-void printiCChain (iCode *icChain, FILE *of)
+void
+printiCChain (iCode * icChain, FILE * of)
 {
 {
-    iCode *loop ;
-    iCodeTable *icTab ;
-
-    if (!of)
-       of = stdout;
-    for ( loop = icChain ; loop ; loop = loop->next ) {
-       if ((icTab = getTableEntry (loop->op ))) {
-           fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
-                   loop->filename,loop->lineno,
-                   loop->seq,loop->key,loop->depth,loop->supportRtn);
+  iCode *loop;
+  iCodeTable *icTab;
 
 
-           icTab->iCodePrint (of,loop,icTab->printName);
-       }
+  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);
+        }
     }
 }
 
     }
 }
 
@@ -410,134 +596,155 @@ void printiCChain (iCode *icChain, FILE *of)
 /*-----------------------------------------------------------------*/
 /* newOperand - allocate, init & return a new iCode                */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* newOperand - allocate, init & return a new iCode                */
 /*-----------------------------------------------------------------*/
-operand *newOperand ()
+operand *
+newOperand ()
 {
 {
-    operand *op ;
-    
-    ALLOC(op,sizeof(operand));
-    
-    op->key = 0 ;
-    return op;
+  operand *op;
+
+  op = Safe_alloc ( sizeof (operand));
+
+  op->key = 0;
+  return op;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiCode - create and return a new iCode entry initialised      */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiCode - create and return a new iCode entry initialised      */
 /*-----------------------------------------------------------------*/
-iCode *newiCode (int op, operand *left, operand *right)
-{
-    iCode *ic ;
-    
-    ALLOC(ic,sizeof(iCode));
-   
-    ic->lineno = lineno ;
-    ic->filename= filename ;
-    ic->block = block;
-    ic->level = scopeLevel;
-    ic->op = op;
-    ic->key= iCodeKey++ ;
-    IC_LEFT(ic) = left;
-    IC_RIGHT(ic)= right;
+iCode *
+newiCode (int op, operand * left, operand * right)
+{
+  iCode *ic;
 
 
-    return ic;
-}      
+  ic = Safe_alloc ( sizeof (iCode));
+
+  ic->seqPoint = seqPoint;
+  ic->lineno = lineno;
+  ic->filename = filename;
+  ic->block = block;
+  ic->level = scopeLevel;
+  ic->op = op;
+  ic->key = iCodeKey++;
+  IC_LEFT (ic) = left;
+  IC_RIGHT (ic) = right;
+
+  return ic;
+}
 
 /*-----------------------------------------------------------------*/
 /* newiCode for conditional statements                             */
 /*-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------*/
 /* newiCode for conditional statements                             */
 /*-----------------------------------------------------------------*/
-iCode *newiCodeCondition (operand *condition,
-                         symbol  *trueLabel, 
-                         symbol  *falseLabel )
+iCode *
+newiCodeCondition (operand * condition,
+                   symbol * trueLabel,
+                   symbol * falseLabel)
 {
 {
-    iCode *ic ;
-    
-    ic = newiCode(IFX,NULL,NULL);
-    IC_COND(ic) = condition ;
-    IC_TRUE(ic) = trueLabel ;
-    IC_FALSE(ic) = falseLabel;
-    return ic;
+  iCode *ic;
+
+  if (IS_VOID(operandType(condition))) {
+    werror(E_VOID_VALUE_USED);
+  }
+
+  ic = newiCode (IFX, NULL, NULL);
+  IC_COND (ic) = condition;
+  IC_TRUE (ic) = trueLabel;
+  IC_FALSE (ic) = falseLabel;
+  return ic;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiCodeLabelGoto - unconditional goto statement| label stmnt   */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiCodeLabelGoto - unconditional goto statement| label stmnt   */
 /*-----------------------------------------------------------------*/
-iCode *newiCodeLabelGoto (int op, symbol *label)
+iCode *
+newiCodeLabelGoto (int op, symbol * label)
 {
 {
-    iCode *ic ;
-    
-    ic = newiCode(op,NULL,NULL);
-    ic->op = op ;
-    ic->argLabel.label = label ;
-    IC_LEFT(ic) = NULL ;
-    IC_RIGHT(ic) = NULL ;
-    IC_RESULT(ic) = NULL ;
-    return ic;
+  iCode *ic;
+
+  ic = newiCode (op, NULL, NULL);
+  ic->op = op;
+  ic->label = label;
+  IC_LEFT (ic) = NULL;
+  IC_RIGHT (ic) = NULL;
+  IC_RESULT (ic) = NULL;
+  return ic;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTemp - allocate & return a newItemp Variable                */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTemp - allocate & return a newItemp Variable                */
 /*-----------------------------------------------------------------*/
-symbol *newiTemp (char *s)
-{ 
-    symbol *itmp;
-    
-    if (s) 
-       sprintf(buffer,"%s",s);
-    else
-       sprintf (buffer,"iTemp%d",iTempNum++);  
-    itmp =  newSymbol (buffer,1);
-    strcpy(itmp->rname,itmp->name);
-    itmp->isitmp = 1;
-    
-    return itmp;
+symbol *
+newiTemp (char *s)
+{
+  symbol *itmp;
+
+  if (s)
+  {
+      SNPRINTF (buffer, sizeof(buffer), "%s", s);
+  }
+  else
+  {
+      SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
+  }
+
+  itmp = newSymbol (buffer, 1);
+  strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
+  itmp->isitmp = 1;
+
+  return itmp;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempLabel - creates a temp variable label                   */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempLabel - creates a temp variable label                   */
 /*-----------------------------------------------------------------*/
-symbol *newiTempLabel (char *s)
+symbol *
+newiTempLabel (char *s)
 {
 {
-    symbol *itmplbl;
+  symbol *itmplbl;
 
 
-    /* check if this alredy exists */
-    if (s && (itmplbl = findSym(LabelTab, NULL, s)))
-       return itmplbl ;
+  /* check if this already exists */
+  if (s && (itmplbl = findSym (LabelTab, NULL, s)))
+    return itmplbl;
 
 
-    if (s) 
-       itmplbl = newSymbol(s,1);
-    else {
-       sprintf(buffer,"iTempLbl%d",iTempLblNum++);
-       itmplbl = newSymbol(buffer,1);  
+  if (s)
+    {
+      itmplbl = newSymbol (s, 1);
+    }
+  else
+    {
+      SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
+      itmplbl = newSymbol (buffer, 1);
     }
     }
-    
-    itmplbl->isitmp = 1;
-    itmplbl->islbl = 1;
-    itmplbl->key = labelKey++ ;
-    addSym (LabelTab, itmplbl, itmplbl->name,0,0);
-    return itmplbl ;  
+
+  itmplbl->isitmp = 1;
+  itmplbl->islbl = 1;
+  itmplbl->key = labelKey++;
+  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
+  return itmplbl;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempPreheaderLabel - creates a new preheader label          */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempPreheaderLabel - creates a new preheader label          */
 /*-----------------------------------------------------------------*/
-symbol *newiTempPreheaderLabel()
+symbol *
+newiTempPreheaderLabel ()
 {
 {
-    symbol *itmplbl ;
+  symbol *itmplbl;
 
 
-    sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
-    itmplbl = newSymbol(buffer,1);    
-    
-    itmplbl->isitmp = 1;
-    itmplbl->islbl = 1;
-    itmplbl->key = labelKey++ ;
-    addSym (LabelTab, itmplbl, itmplbl->name,0,0);
-    return itmplbl ;  
+  SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
+  itmplbl = newSymbol (buffer, 1);
+
+  itmplbl->isitmp = 1;
+  itmplbl->islbl = 1;
+  itmplbl->key = labelKey++;
+  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
+  return itmplbl;
 }
 
 
 /*-----------------------------------------------------------------*/
 /* initiCode - initialises some iCode related stuff                */
 /*-----------------------------------------------------------------*/
 }
 
 
 /*-----------------------------------------------------------------*/
 /* initiCode - initialises some iCode related stuff                */
 /*-----------------------------------------------------------------*/
-void initiCode ()
+void
+initiCode ()
 {
 
 }
 {
 
 }
@@ -545,1467 +752,2105 @@ void initiCode ()
 /*-----------------------------------------------------------------*/
 /* copyiCode - make a copy of the iCode given                      */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* copyiCode - make a copy of the iCode given                      */
 /*-----------------------------------------------------------------*/
-iCode *copyiCode (iCode *ic)
+iCode *
+copyiCode (iCode * ic)
 {
 {
-    iCode *nic = newiCode(ic->op,NULL,NULL);
+  iCode *nic = newiCode (ic->op, NULL, NULL);
 
 
-    nic->lineno = ic->lineno ;
-    nic->filename= ic->filename ;
-    nic->block = ic->block;
-    nic->level = ic->level;
+  nic->lineno = ic->lineno;
+  nic->filename = ic->filename;
+  nic->block = ic->block;
+  nic->level = ic->level;
+  nic->parmBytes = ic->parmBytes;
 
 
-    /* deal with the special cases first */
-    switch (ic->op) {
+  /* deal with the special cases first */
+  switch (ic->op)
+    {
     case IFX:
     case IFX:
-       IC_COND(nic) = operandFromOperand(IC_COND(ic));
-       IC_TRUE(nic) = IC_TRUE(ic);
-       IC_FALSE(nic)= IC_FALSE(ic);
-       break;
+      IC_COND (nic) = operandFromOperand (IC_COND (ic));
+      IC_TRUE (nic) = IC_TRUE (ic);
+      IC_FALSE (nic) = IC_FALSE (ic);
+      break;
 
     case JUMPTABLE:
 
     case JUMPTABLE:
-       IC_JTCOND(nic) = operandFromOperand(IC_JTCOND(ic));
-       IC_JTLABELS(nic) = IC_JTLABELS(ic);
-       break;
+      IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
+      IC_JTLABELS (nic) = IC_JTLABELS (ic);
+      break;
 
     case CALL:
     case PCALL:
 
     case CALL:
     case PCALL:
-       IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
-       IC_LEFT(nic)   = operandFromOperand(IC_LEFT(ic));
-       IC_ARGS(nic)   = IC_ARGS(ic);
-       break;
+      IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
+      IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
+      break;
 
     case INLINEASM:
 
     case INLINEASM:
-       IC_INLINE(nic) = IC_INLINE(ic);
-       break;
-       
+      IC_INLINE (nic) = IC_INLINE (ic);
+      break;
+
+    case ARRAYINIT:
+      IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
+      break;
+
     default:
     default:
-       IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
-       IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
-       IC_RIGHT(nic)= operandFromOperand(IC_RIGHT(ic));
+      IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
+      IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
+      IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
     }
 
     }
 
-    return nic;
+  return nic;
 }
 
 /*-----------------------------------------------------------------*/
 /* getTableEntry - gets the table entry for the given operator     */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* getTableEntry - gets the table entry for the given operator     */
 /*-----------------------------------------------------------------*/
-iCodeTable *getTableEntry (int oper )
+iCodeTable *
+getTableEntry (int oper)
 {
 {
-    int i ;
-    
-    for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ ) 
-       if (oper == codeTable[i].icode)
-           return &codeTable[i] ;
-    
-    return NULL ;
+  unsigned i;
+
+  for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
+    if (oper == codeTable[i].icode)
+      return &codeTable[i];
+
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempOperand - new intermediate temp operand                 */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempOperand - new intermediate temp operand                 */
 /*-----------------------------------------------------------------*/
-operand *newiTempOperand (link *type, char throwType)
+operand *
+newiTempOperand (sym_link * type, char throwType)
 {
 {
-    symbol *itmp;
-    operand *op = newOperand();
-    link *etype;
+  symbol *itmp;
+  operand *op = newOperand ();
+  sym_link *etype;
 
 
-    op->type = SYMBOL ;
-    itmp = newiTemp(NULL);
+  op->type = SYMBOL;
+  itmp = newiTemp (NULL);
 
 
-    etype = getSpec(type);
+  etype = getSpec (type);
 
 
-    if (IS_LITERAL(etype) )
-       throwType = 0 ;
+  if (IS_LITERAL (etype))
+    throwType = 0;
 
 
-    /* copy the type information */
-    if (type) 
-       itmp->etype = getSpec (itmp->type = (throwType ? type :
-                                            copyLinkChain(type)));
-    if (IS_LITERAL(itmp->etype)) {
-       SPEC_SCLS(itmp->etype) = S_REGISTER ;
-       SPEC_OCLS(itmp->etype) = reg;
+  /* copy the type information */
+  if (type)
+    itmp->etype = getSpec (itmp->type = (throwType ? type :
+                                         copyLinkChain (type)));
+  if (IS_LITERAL (itmp->etype))
+    {
+      SPEC_SCLS (itmp->etype) = S_REGISTER;
+      SPEC_OCLS (itmp->etype) = reg;
     }
     }
-       
-    op->operand.symOperand = itmp;
-    op->key = itmp->key = ++operandKey ;
-    return op;
+
+  op->operand.symOperand = itmp;
+  op->key = itmp->key = ++operandKey;
+  return op;
 }
 
 /*-----------------------------------------------------------------*/
 /* operandType - returns the type chain for an operand             */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operandType - returns the type chain for an operand             */
 /*-----------------------------------------------------------------*/
-link *operandType (operand *op) 
+sym_link *
+operandType (operand * op)
 {
 {
-    /* depending on type of operand */
-    switch (op->type) {
-       
-    case VALUE :
-       return op->operand.valOperand->type ;
-       
+  /* depending on type of operand */
+  switch (op->type)
+    {
+
+    case VALUE:
+      return op->operand.valOperand->type;
+
     case SYMBOL:
     case SYMBOL:
-       return op->operand.symOperand->type ;
-       
-    case TYPE :
-       return op->operand.typeOperand ;
+      return op->operand.symOperand->type;
+
+    case TYPE:
+      return op->operand.typeOperand;
     default:
     default:
-       werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
-               " operand type not known ");
-       assert (0) ; /* should never come here */
-       /*  Just to keep the compiler happy */
-       return (link *)0;
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              " operand type not known ");
+      assert (0);               /* should never come here */
+      /*  Just to keep the compiler happy */
+      return (sym_link *) 0;
     }
 }
 
 /*-----------------------------------------------------------------*/
 /* isParamterToCall - will return 1 if op is a parameter to args   */
 /*-----------------------------------------------------------------*/
     }
 }
 
 /*-----------------------------------------------------------------*/
 /* isParamterToCall - will return 1 if op is a parameter to args   */
 /*-----------------------------------------------------------------*/
-int isParameterToCall (value *args, operand *op)
+int
+isParameterToCall (value * args, operand * op)
 {
 {
-    value *tval = args ;
+  value *tval = args;
+
+  wassert (IS_SYMOP(op));
 
 
-    while (tval) {
-       if (tval->sym && 
-           isSymbolEqual(op->operand.symOperand,tval->sym))
-           return 1;
-       tval = tval->next ;
+  while (tval)
+    {
+      if (tval->sym &&
+          isSymbolEqual (op->operand.symOperand, tval->sym))
+        return 1;
+      tval = tval->next;
     }
     }
-    return 0;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* isOperandGlobal   - return 1 if operand is a global variable    */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* isOperandGlobal   - return 1 if operand is a global variable    */
 /*-----------------------------------------------------------------*/
-int isOperandGlobal ( operand *op )
+int
+isOperandGlobal (operand * op)
 {
 {
-    if (!op)
-       return 0;
-
-    if (IS_ITEMP(op))
-       return 0;
+  if (!op)
+    return 0;
 
 
-    if (op->type == SYMBOL &&       
-        (op->operand.symOperand->level == 0 ||  
-        IS_STATIC(op->operand.symOperand->etype) ||
-        IS_EXTERN(op->operand.symOperand->etype))
-         )
-       return 1;
-    
+  if (IS_ITEMP (op))
     return 0;
     return 0;
+
+  if (IS_SYMOP(op) &&
+      (op->operand.symOperand->level == 0 ||
+       IS_STATIC (op->operand.symOperand->etype) ||
+       IS_EXTERN (op->operand.symOperand->etype))
+    )
+    return 1;
+
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* isOperandVolatile - return 1 if the operand is volatile         */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* isOperandVolatile - return 1 if the operand is volatile         */
 /*-----------------------------------------------------------------*/
-int isOperandVolatile ( operand *op , bool chkTemp)
+int
+isOperandVolatile (operand * op, bool chkTemp)
 {
 {
-    link *optype ;
-    link *opetype ;
+  sym_link *optype;
+  sym_link *opetype;
+
+  if (IS_ITEMP (op) && !chkTemp)
+    return 0;
 
 
-    if (IS_ITEMP(op) && !chkTemp)
-       return 0;
+  opetype = getSpec (optype = operandType (op));
 
 
-    opetype = getSpec(optype = operandType(op));
-    
-    if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
-       return 1;
+  if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
+    return 1;
 
 
-    if (IS_VOLATILE(opetype))
-       return 1;
-    return 0;
+  if (IS_VOLATILE (opetype))
+    return 1;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* isOperandLiteral - returns 1 if an operand contains a literal   */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* isOperandLiteral - returns 1 if an operand contains a literal   */
 /*-----------------------------------------------------------------*/
-int isOperandLiteral ( operand *op )
+int
+isOperandLiteral (operand * op)
 {
 {
-    link *opetype ;
-    
-    if (!op)
-       return 0;
-    
-    opetype = getSpec (operandType(op));
-
-    if (IS_LITERAL(opetype))
-       return 1;
+  sym_link *opetype;
 
 
+  if (!op)
     return 0;
     return 0;
+
+  opetype = getSpec (operandType (op));
+
+  if (IS_LITERAL (opetype))
+    return 1;
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* isOperandInFarSpace - will return true if operand is in farSpace */
+/*-----------------------------------------------------------------*/
+bool
+isOperandInFarSpace (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_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
+/*------------------------------------------------------------------*/
+/* isOperandInDirSpace - will return true if operand is in dirSpace */
+/*------------------------------------------------------------------*/
+bool
+isOperandInDirSpace (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_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
+/*--------------------------------------------------------------------*/
+/* isOperandInCodeSpace - will return true if operand is in codeSpace */
+/*--------------------------------------------------------------------*/
+bool
+isOperandInCodeSpace (operand * op)
+{
+  sym_link *etype;
+
+  if (!op)
+    return FALSE;
+
+  if (!IS_SYMOP (op))
+    return FALSE;
+
+  etype = getSpec (operandType (op));
+
+  if (!IS_TRUE_SYMOP (op))
+    {
+      if (SPIL_LOC (op))
+        etype = SPIL_LOC (op)->etype;
+      else
+        return FALSE;
+    }
+  else
+    {
+      etype = getSpec (operandType (op));
+    }
+  return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
+/*-----------------------------------------------------------------*/
+/* isOperandOnStack - will return true if operand is on stack      */
+/*-----------------------------------------------------------------*/
+bool
+isOperandOnStack (operand * op)
+{
+  sym_link *etype;
+
+  if (!op)
+    return FALSE;
+
+  if (!IS_SYMOP (op))
+    return FALSE;
+
+  etype = getSpec (operandType (op));
+  if (IN_STACK (etype) ||
+      OP_SYMBOL(op)->onStack ||
+      (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
+    return TRUE;
+
+  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);
 }
 }
+
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-/* isOperandInFarSpace - will return true if operand is in farSpace*/
+/* isiCodeInFunctionCall - return TRUE if an iCode is between a    */
+/*   CALL/PCALL and the first IPUSH/SEND associated with the call  */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-bool isOperandInFarSpace (operand *op)
+int
+isiCodeInFunctionCall (iCode * ic)
 {
 {
-    link *etype;
+  iCode * lic = ic;
 
 
-    if (!op)
-       return FALSE;
+  /* Find the next CALL/PCALL */
+  while (lic)
+    {
+      if (lic->op == CALL || lic->op == PCALL)
+        break;
+      lic = lic->next;
+    }
 
 
-    if (!IS_SYMOP(op))
-       return FALSE ;
+  if (!lic)
+    return FALSE;
 
 
-    if (!IS_TRUE_SYMOP(op)) {
-       if (SPIL_LOC(op))
-           etype = SPIL_LOC(op)->etype;
-       else            
-           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;
     }
 
     }
 
-    etype = getSpec(operandType(op));
-    return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
 /* operandLitValue - literal value of an operand                   */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operandLitValue - literal value of an operand                   */
 /*-----------------------------------------------------------------*/
-double operandLitValue ( operand *op )
+double
+operandLitValue (operand * op)
+{
+  assert (isOperandLiteral (op));
+
+  return floatFromVal (op->operand.valOperand);
+}
+
+/*-----------------------------------------------------------------*/
+/* getBuiltInParms - returns parameters to a builtin functions     */
+/*-----------------------------------------------------------------*/
+iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
 {
 {
-    assert(isOperandLiteral(op));
-    
-    return floatFromVal(op->operand.valOperand);    
+    sym_link *ftype;
+
+    *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)++;
+    }
+
+    ic->generated = 1;
+    /* make sure this is a builtin function call */
+    assert(IS_SYMOP(IC_LEFT(ic)));
+    ftype = operandType(IC_LEFT(ic));
+    assert(IFFUNC_ISBUILTIN(ftype));
+    return ic;
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
-/* operandOperation - perforoms operations on operands             */
+/* operandOperation - performs operations on operands             */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-operand *operandOperation (operand *left,operand *right,
-                          int op, link *type)
+operand *
+operandOperation (operand * left, operand * right,
+                  int op, sym_link * type)
 {
 {
-    operand *retval = (operand *)0;
-        
-    assert(isOperandLiteral(left));
-    if (right) 
-       assert(isOperandLiteral(right));
-    
-    switch (op) {
-    case '+' :
-       retval =  operandFromValue (valCastLiteral(type,
-                                                  operandLitValue(left) + 
-                                                  operandLitValue(right)));
-       break ;
-    case '-' :
-       retval = operandFromValue(valCastLiteral(type,
-                                                operandLitValue(left) -
-                                                operandLitValue(right)));
-       break;
+  sym_link *let , *ret=NULL;
+  operand *retval = (operand *) 0;
+
+  assert (isOperandLiteral (left));
+  let = getSpec(operandType(left));
+  if (right) {
+    assert (isOperandLiteral (right));
+    ret = getSpec(operandType(right));
+  }
+
+  switch (op)
+    {
+    case '+':
+      retval = operandFromValue (valCastLiteral (type,
+                                                 operandLitValue (left) +
+                                                 operandLitValue (right)));
+      break;
+    case '-':
+      retval = operandFromValue (valCastLiteral (type,
+                                                 operandLitValue (left) -
+                                                 operandLitValue (right)));
+      break;
     case '*':
     case '*':
-       retval = operandFromValue(valCastLiteral(type,
-                                                operandLitValue(left) *
-                                                operandLitValue(right)));
-       break;
+      /*
+      retval = operandFromValue (valCastLiteral (type,
+                                                 operandLitValue (left) *
+                                                 operandLitValue (right)));
+      This could be all we've to do, but with gcc we've to take care about
+      overflows. Two examples:
+      ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
+      significant bits are lost (52 in fraction, 63 bits would be
+      necessary to keep full precision).
+      If the resulting double value is greater than ULONG_MAX (resp.
+      USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
+      */
+
+      /* if it is not a specifier then we can assume that */
+      /* it will be an unsigned long                      */
+      if (IS_INT (type) ||
+          !IS_SPEC (type))
+        {
+          /* long is handled here, because it can overflow with double */
+          if (IS_LONG (type) ||
+              !IS_SPEC (type))
+          /* signed and unsigned mul are the same, as long as the precision
+             of the result isn't bigger than the precision of the operands. */
+            retval = operandFromValue (valCastLiteral (type,
+                     (TYPE_UDWORD) operandLitValue (left) *
+                     (TYPE_UDWORD) operandLitValue (right)));
+          else if (IS_UNSIGNED (type)) /* unsigned int */
+            {
+              /* unsigned int is handled here in order to detect overflow */
+              TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
+                               (TYPE_UWORD) operandLitValue (right);
+
+              retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
+              if (ul != (TYPE_UWORD) ul)
+                werror (W_INT_OVL);
+            }
+          else /* signed int */
+            {
+              /* signed int is handled here in order to detect overflow */
+              TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
+                             (TYPE_WORD) operandLitValue (right);
+
+              retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
+              if (l != (TYPE_WORD) l)
+                werror (W_INT_OVL);
+            }
+        }
+      else
+        /* all others go here: */
+        retval = operandFromValue (valCastLiteral (type,
+                                                   operandLitValue (left) *
+                                                   operandLitValue (right)));
+      break;
     case '/':
     case '/':
-       if ((unsigned long) operandLitValue(right) == 0){           
-           werror(E_DIVIDE_BY_ZERO);
-           retval = right;
-           
-       }
-       else
-           retval = operandFromValue (valCastLiteral(type,
-                                                     operandLitValue(left) /
-                                                     operandLitValue(right)));
-       break;
-    case '%':      
-       if ((unsigned long) operandLitValue(right) == 0){           
-           werror(E_DIVIDE_BY_ZERO);
-           retval = right;         
-       }
-       else
-           retval = operandFromLit ((unsigned long) operandLitValue(left) %
-                                    (unsigned long) operandLitValue(right));
-       break;
-    case LEFT_OP :
-       retval = operandFromLit ((unsigned long) operandLitValue(left) <<
-                                (unsigned long) operandLitValue(right));
-       break;
-    case RIGHT_OP :
-       retval = operandFromLit ((unsigned long) operandLitValue(left) >>
-                                (unsigned long) operandLitValue(right));
-       break;
-    case EQ_OP :
-       retval = operandFromLit (operandLitValue(left) ==
-                                operandLitValue(right));
-       break;
-    case '<' :
-       retval = operandFromLit (operandLitValue(left) <
-                                operandLitValue(right));
-       break;
-    case LE_OP :
-       retval = operandFromLit (operandLitValue(left) <=
-                                operandLitValue(right));
-       break;
-    case NE_OP :
-       retval = operandFromLit (operandLitValue(left) !=
-                                operandLitValue(right));
-       break;
-    case '>' :
-       retval = operandFromLit (operandLitValue(left) >
-                                operandLitValue(right));
-       break;
-    case GE_OP :
-       retval = operandFromLit (operandLitValue(left) >=
-                                operandLitValue(right));
-       break;
-    case BITWISEAND :
-       retval = operandFromLit ((unsigned long) operandLitValue(left) &
-                                (unsigned long) operandLitValue(right));
-       break;
-    case '|' :
-       retval = operandFromLit ((unsigned long) operandLitValue(left) |
-                                (unsigned long) operandLitValue(right));       
-       break;
-    case '^' :
-       retval = operandFromLit ((unsigned long) operandLitValue(left) ^
-                                (unsigned long) operandLitValue(right));
-       break;
+      if ((TYPE_UDWORD) operandLitValue (right) == 0)
+        {
+          werror (E_DIVIDE_BY_ZERO);
+          retval = right;
+
+        }
+      else
+        {
+          if (IS_UNSIGNED (type))
+            {
+              SPEC_USIGN (let) = 1;
+              SPEC_USIGN (ret) = 1;
+              retval = operandFromValue (valCastLiteral (type,
+                                        (TYPE_UDWORD) operandLitValue (left) /
+                                        (TYPE_UDWORD) operandLitValue (right)));
+            }
+          else
+            {
+              retval = operandFromValue (valCastLiteral (type,
+                                                     operandLitValue (left) /
+                                                     operandLitValue (right)));
+            }
+        }
+      break;
+    case '%':
+      if ((TYPE_UDWORD) operandLitValue (right) == 0)
+        {
+          werror (E_DIVIDE_BY_ZERO);
+          retval = right;
+        }
+      else
+        {
+          if (IS_UNSIGNED (type))
+            retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
+                                     (TYPE_UDWORD) operandLitValue (right));
+          else
+            retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
+                                     (TYPE_DWORD) operandLitValue (right));
+        }
+      break;
+    case LEFT_OP:
+      /* The number of left shifts is always unsigned. Signed doesn't make
+         sense here. Shifting by a negative number is impossible. */
+      retval = operandFromValue (valCastLiteral (type,
+                                 ((TYPE_UDWORD) operandLitValue (left) <<
+                                  (TYPE_UDWORD) operandLitValue (right))));
+      break;
+    case RIGHT_OP:
+      /* The number of right shifts is always unsigned. Signed doesn't make
+         sense here. Shifting by a negative number is impossible. */
+      if (IS_UNSIGNED(let))
+        /* unsigned: logic shift right */
+        retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
+                                 (TYPE_UDWORD) operandLitValue (right));
+      else
+        /* signed: arithmetic shift right */
+        retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
+                                 (TYPE_UDWORD) operandLitValue (right));
+      break;
+    case EQ_OP:
+      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_UDWORD l, r;
+
+          l = (TYPE_UDWORD) operandLitValue (left);
+          r = (TYPE_UDWORD) operandLitValue (right);
+          /* In order to correctly compare 'signed int' and 'unsigned int' it's
+             neccessary to strip them to 16 bit.
+             Literals are reduced to their cheapest type, therefore left and
+             right might have different types. It's neccessary to find a
+             common type: int (used for char too) or long */
+          if (!IS_LONG (let) &&
+              !IS_LONG (ret))
+            {
+              r = (TYPE_UWORD) r;
+              l = (TYPE_UWORD) l;
+            }
+          retval = operandFromLit (l == r);
+        }
+      break;
+    case '<':
+      retval = operandFromLit (operandLitValue (left) <
+                               operandLitValue (right));
+      break;
+    case LE_OP:
+      retval = operandFromLit (operandLitValue (left) <=
+                               operandLitValue (right));
+      break;
+    case NE_OP:
+      retval = operandFromLit (operandLitValue (left) !=
+                               operandLitValue (right));
+      break;
+    case '>':
+      retval = operandFromLit (operandLitValue (left) >
+                               operandLitValue (right));
+      break;
+    case GE_OP:
+      retval = operandFromLit (operandLitValue (left) >=
+                               operandLitValue (right));
+      break;
+    case BITWISEAND:
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) &
+                                                 (TYPE_UDWORD)operandLitValue(right)));
+      break;
+    case '|':
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) |
+                                                 (TYPE_UDWORD)operandLitValue(right)));
+      break;
+    case '^':
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) ^
+                                                 (TYPE_UDWORD)operandLitValue(right)));
+      break;
     case AND_OP:
     case AND_OP:
-       retval = operandFromLit (operandLitValue(left) &&
-                                operandLitValue(right));
-       break;
+      retval = operandFromLit (operandLitValue (left) &&
+                               operandLitValue (right));
+      break;
     case OR_OP:
     case OR_OP:
-       retval = operandFromLit (operandLitValue(left) ||
-                                operandLitValue(right));
-       break;
+      retval = operandFromLit (operandLitValue (left) ||
+                               operandLitValue (right));
+      break;
     case RRC:
     case RRC:
-       {
-           long i = operandLitValue(left);
-           
-           retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
-                                    (i << 1));
-       }
-       break;
+      {
+        TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
+
+        retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
+                                 (i << 1));
+      }
+      break;
     case RLC:
     case RLC:
-       {
-           long i = operandLitValue(left);
-           
-           retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
-                                    (i >> 1));
-       }
-       break;
-       
+      {
+        TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
+
+        retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
+                                 (i >> 1));
+      }
+      break;
+
     case UNARYMINUS:
     case UNARYMINUS:
-       retval = operandFromLit(-1 * operandLitValue(left));
-       break;
-       
+      retval = operandFromValue (valCastLiteral (type,
+                                                 -1 * operandLitValue (left)));
+      break;
+
     case '~':
     case '~':
-       retval = operandFromLit(~ ((long) operandLitValue(left)));
-       break;
+      retval = operandFromValue (valCastLiteral (type,
+                                                 ~((TYPE_UDWORD)
+                                                   operandLitValue (left))));
+      break;
 
     case '!':
 
     case '!':
-       retval = operandFromLit(! operandLitValue(left));
-       break;
+      retval = operandFromLit (!operandLitValue (left));
+      break;
 
 
-    default :
-       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-              " operandOperation invalid operator ");
-       assert (0);
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              " operandOperation invalid operator ");
+      assert (0);
     }
     }
-    
-    return retval;
+
+  return retval;
 }
 
 
 /*-----------------------------------------------------------------*/
 /* isOperandEqual - compares two operand & return 1 if they r =    */
 /*-----------------------------------------------------------------*/
 }
 
 
 /*-----------------------------------------------------------------*/
 /* isOperandEqual - compares two operand & return 1 if they r =    */
 /*-----------------------------------------------------------------*/
-int isOperandEqual (operand *left, operand *right)
+int
+isOperandEqual (operand * left, operand * right)
 {
 {
-    /* if the pointers are equal then they are equal */
-    if ( left == right )
-       return 1;
-    
-    /* if either of them null then false */
-    if ( !left || !right)
-       return 0;
+  /* if the pointers are equal then they are equal */
+  if (left == right)
+    return 1;
+
+  /* if either of them null then false */
+  if (!left || !right)
+    return 0;
 
 
-    if (left->type != right->type)
-       return 0;
+  if (left->type != right->type)
+    return 0;
 
 
-    if (IS_SYMOP(left) && IS_SYMOP(right))
-       return left->key == right->key ;
+  if (IS_SYMOP (left) && IS_SYMOP (right))
+    return left->key == right->key;
 
 
-    /* if types are the same */
-    switch (left->type) {
-    case SYMBOL :
-       return isSymbolEqual(left->operand.symOperand,
-                            right->operand.symOperand);
-    case VALUE :
-       return (floatFromVal(left->operand.valOperand) ==
-               floatFromVal(right->operand.valOperand));
-    case TYPE :
-       if (checkType(left->operand.typeOperand,
-                     right->operand.typeOperand) == 1)
-           return 1;      
+  /* if types are the same */
+  switch (left->type)
+    {
+    case SYMBOL:
+      return isSymbolEqual (left->operand.symOperand,
+                            right->operand.symOperand);
+    case VALUE:
+      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;
     }
 
     }
 
-    return 0;
+  return 0;
 }
 
 }
 
-/*-----------------------------------------------------------------*/
-/* isiCodeEqual - comapres two iCodes are returns true if yes      */
-/*-----------------------------------------------------------------*/
-int isiCodeEqual (iCode *left, iCode *right)
+/*-------------------------------------------------------------------*/
+/* isiCodeEqual - compares two iCodes are equal, returns true if yes */
+/*-------------------------------------------------------------------*/
+int
+isiCodeEqual (iCode * left, iCode * right)
 {
 {
-    /* if the same pointer */
-    if (left == right)
-       return 1;
-    
-    /* if either of them null */
-    if (!left || !right)
-       return 0;
+  /* if the same pointer */
+  if (left == right)
+    return 1;
+
+  /* if either of them null */
+  if (!left || !right)
+    return 0;
 
 
-    /* if operand are the same */
-    if ( left->op == right->op ) {
-       
-       /* 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 operand are the same */
+  if (left->op == right->op)
+    {
 
 
-       } 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;
-       }
-       return 1;
+      /* 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;
+
+        }
+      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;
+        }
+
+      return 1;
     }
     }
-    return 0;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempFromOp - create a temp Operand with same attributes     */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiTempFromOp - create a temp Operand with same attributes     */
 /*-----------------------------------------------------------------*/
-operand *newiTempFromOp (operand *op)
+operand *
+newiTempFromOp (operand * op)
 {
 {
-    operand *nop;
+  operand *nop;
+
+  if (!op)
+    return NULL;
 
 
-    if (!op)
-       return NULL;
-    
-    if (!IS_ITEMP(op))
-       return op;
+  if (!IS_ITEMP (op))
+    return op;
 
 
-    nop = newiTempOperand(operandType(op),TRUE);
-    nop->isaddr = op->isaddr ;
-    nop->isvolatile = op->isvolatile ;
-    nop->isGlobal = op->isGlobal ;
-    nop->isLiteral= op->isLiteral ;
-    nop->noSpilLoc= op->noSpilLoc;
-    nop->usesDefs = op->usesDefs;
-    nop->isParm = op->isParm;
-    nop->parmBytes = op->parmBytes;
-    return nop;
+  nop = newiTempOperand (operandType (op), TRUE);
+  nop->isaddr = op->isaddr;
+  nop->isvolatile = op->isvolatile;
+  nop->isGlobal = op->isGlobal;
+  nop->isLiteral = op->isLiteral;
+  nop->usesDefs = op->usesDefs;
+  nop->isParm = op->isParm;
+  return nop;
 }
 
 /*-----------------------------------------------------------------*/
 /* operand from operand - creates an operand holder for the type   */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operand from operand - creates an operand holder for the type   */
 /*-----------------------------------------------------------------*/
-operand *operandFromOperand (operand *op)
-{
-    operand *nop ;
-    
-    if (!op)
-       return NULL;
-    nop = newOperand();
-    nop->type = op->type;
-    nop->isaddr = op->isaddr ;
-    nop->key = op->key ;
-    nop->isvolatile = op->isvolatile ;
-    nop->isGlobal = op->isGlobal ;
-    nop->isLiteral= op->isLiteral ;
-    nop->noSpilLoc= op->noSpilLoc;
-    nop->usesDefs = op->usesDefs;
-    nop->isParm = op->isParm;
-    nop->parmBytes = op->parmBytes;
-
-    switch (nop->type) {
-    case SYMBOL :
-       nop->operand.symOperand = op->operand.symOperand ;      
-       break;
-    case VALUE :
-       nop->operand.valOperand = op->operand.valOperand;
-       break;
-    case TYPE :
-       nop->operand.typeOperand = op->operand.typeOperand ;
-       break ;
-    }   
-
-    return nop;
+operand *
+operandFromOperand (operand * op)
+{
+  operand *nop;
+
+  if (!op)
+    return NULL;
+  nop = newOperand ();
+  nop->type = op->type;
+  nop->isaddr = op->isaddr;
+  nop->key = op->key;
+  nop->isvolatile = op->isvolatile;
+  nop->isGlobal = op->isGlobal;
+  nop->isLiteral = op->isLiteral;
+  nop->usesDefs = op->usesDefs;
+  nop->isParm = op->isParm;
+
+  switch (nop->type)
+    {
+    case SYMBOL:
+      nop->operand.symOperand = op->operand.symOperand;
+      break;
+    case VALUE:
+      nop->operand.valOperand = op->operand.valOperand;
+      break;
+    case TYPE:
+      nop->operand.typeOperand = op->operand.typeOperand;
+      break;
+    }
+
+  return nop;
 }
 
 /*-----------------------------------------------------------------*/
 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
 /*-----------------------------------------------------------------*/
-operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
+operand *
+opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
 {
 {
-    operand *nop = operandFromOperand(op);
+  operand *nop = operandFromOperand (op);
 
 
-    if (nop->type == SYMBOL) {
-       OP_SYMBOL(nop)->defs = bitVectCopy(defs);
-       OP_SYMBOL(nop)->uses = bitVectCopy(uses);
+  if (nop->type == SYMBOL)
+    {
+      OP_SYMBOL (nop)->defs = bitVectCopy (defs);
+      OP_SYMBOL (nop)->uses = bitVectCopy (uses);
     }
 
     }
 
-    return nop;
+  return nop;
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromSymbol - creates an operand from a symbol            */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromSymbol - creates an operand from a symbol            */
 /*-----------------------------------------------------------------*/
-operand *operandFromSymbol (symbol *sym)
-{
-    operand *op ;
-    iCode *ic ;
-    int ok =1 ;
-    /* if the symbol's type is a literal */
-    /* then it is an enumerator type     */
-    if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype)) 
-       return operandFromValue (valFromType(sym->etype));
-
-    if (!sym->key)
-       sym->key = ++operandKey ;
-
-    /* if this an implicit variable, means struct/union */
-    /* member so just return it                         */
-    if (sym->implicit || IS_FUNC(sym->type)) {
-       op = newOperand();
-       op->type = SYMBOL ;
-       op->operand.symOperand = sym;
-       op->key = sym->key ;
-       op->isvolatile = isOperandVolatile(op,TRUE);
-       op->isGlobal   = isOperandGlobal(op);
-       op->parmBytes  = sym->argStack;
-       return op;
-    }
-    
-    /* under the following conditions create a
-       register equivalent for a local symbol */
-    if (sym->level && sym->etype && SPEC_OCLS(sym->etype) &&
-       IN_FARSPACE(SPEC_OCLS(sym->etype))  &&
-       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 register euivalence */
-       !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 */
-       ) {
-       
-       /* we will use it after all optimizations
-          and before liveRange calculation */
-       sym->reqv = newiTempOperand(sym->type,0);       
-       sym->reqv->key = sym->key ;
-       OP_SYMBOL(sym->reqv)->key = sym->key;
-       OP_SYMBOL(sym->reqv)->isreqv = 1;
-       OP_SYMBOL(sym->reqv)->islocal = 1;
-       SPIL_LOC(sym->reqv) = sym;
-    }
-   
-    if (!IS_AGGREGATE(sym->type)) {
-       op = newOperand();
-       op->type = SYMBOL;
-       op->operand.symOperand = sym;
-       op->isaddr = 1;
-       op->key = sym->key;
-       op->isvolatile = isOperandVolatile(op,TRUE);
-       op->isGlobal   = isOperandGlobal(op);
-       op->isPtr = IS_PTR(operandType(op));
-       op->isParm = sym->_isparm ;
-       return op;
-    }
-    
-    /* create :-                     */
-    /*    itemp = &[_symbol]         */
-    
-    ic = newiCode(ADDRESS_OF,newOperand(),NULL);
-    IC_LEFT(ic)->type = SYMBOL ;
-    IC_LEFT(ic)->operand.symOperand = sym ;
-    IC_LEFT(ic)->key = sym->key;    
-    (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
-    (IC_LEFT(ic))->isGlobal   = isOperandGlobal(IC_LEFT(ic));
-    IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
-
-    /* create result */
-    IC_RESULT(ic) = newiTempOperand(sym->type,0);
-    if (IS_ARRAY(sym->type)) {
-       IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
-       IC_RESULT(ic)->isaddr = 0;
-    } else
-       IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
-
-    IC_RESULT(ic)->operand.symOperand->args = sym->args;
-
-    ADDTOCHAIN(ic);
-    
-    return IC_RESULT(ic) ;
+operand *
+operandFromSymbol (symbol * sym)
+{
+  operand *op;
+  iCode *ic;
+  int ok = 1;
+  /* if the symbol's type is a literal */
+  /* then it is an enumerator type     */
+  if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
+    return operandFromValue (valFromType (sym->etype));
+
+  if (!sym->key)
+    sym->key = ++operandKey;
+
+  /* if this an implicit variable, means struct/union */
+  /* member so just return it                         */
+  if (sym->implicit || IS_FUNC (sym->type))
+    {
+      op = newOperand ();
+      op->type = SYMBOL;
+      op->operand.symOperand = sym;
+      op->key = sym->key;
+      op->isvolatile = isOperandVolatile (op, TRUE);
+      op->isGlobal = isOperandGlobal (op);
+      return op;
+    }
+
+  /* under the following conditions create a
+     register equivalent for a local symbol */
+  if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
+      (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+      !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  */
+      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 */
+    )
+    {
+
+      /* we will use it after all optimizations
+         and before liveRange calculation */
+      sym->reqv = newiTempOperand (sym->type, 0);
+      sym->reqv->key = sym->key;
+      OP_SYMBOL (sym->reqv)->prereqv = sym;
+      OP_SYMBOL (sym->reqv)->key = sym->key;
+      OP_SYMBOL (sym->reqv)->isreqv = 1;
+      OP_SYMBOL (sym->reqv)->islocal = 1;
+      OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
+      SPIL_LOC (sym->reqv) = sym;
+    }
+
+  if (!IS_AGGREGATE (sym->type))
+    {
+      op = newOperand ();
+      op->type = SYMBOL;
+      op->operand.symOperand = sym;
+      op->isaddr = 1;
+      op->key = sym->key;
+      op->isvolatile = isOperandVolatile (op, TRUE);
+      op->isGlobal = isOperandGlobal (op);
+      op->isPtr = IS_PTR (operandType (op));
+      op->isParm = sym->_isparm;
+      return op;
+    }
+
+  /* create :-                     */
+  /*    itemp = &[_symbol]         */
+
+  ic = newiCode (ADDRESS_OF, newOperand (), NULL);
+  IC_LEFT (ic)->type = SYMBOL;
+  IC_LEFT (ic)->operand.symOperand = sym;
+  IC_LEFT (ic)->key = sym->key;
+  (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
+  (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
+  IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
+
+  /* create result */
+  IC_RESULT (ic) = newiTempOperand (sym->type, 0);
+  if (IS_ARRAY (sym->type))
+    {
+      IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
+      IC_RESULT (ic)->isaddr = 0;
+    }
+  else
+    IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
+
+  ADDTOCHAIN (ic);
+
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromValue - creates an operand from value                */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromValue - creates an operand from value                */
 /*-----------------------------------------------------------------*/
-operand *operandFromValue (value *val)
-{
-    operand *op ;
-    
-    /* if this is a symbol then do the symbol thing */
-    if (val->sym)
-       return operandFromSymbol (val->sym);
-    
-    /* this is not a symbol */
-    op = newOperand();
-    op->type = VALUE ;
-    op->operand.valOperand = val ;
-    op->isLiteral = isOperandLiteral(op);
-    return op;
+operand *
+operandFromValue (value * val)
+{
+  operand *op;
+
+  /* if this is a symbol then do the symbol thing */
+  if (val->sym)
+    return operandFromSymbol (val->sym);
+
+  /* this is not a symbol */
+  op = newOperand ();
+  op->type = VALUE;
+  op->operand.valOperand = val;
+  op->isLiteral = isOperandLiteral (op);
+  return op;
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromLink - operand from typeChain                        */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromLink - operand from typeChain                        */
 /*-----------------------------------------------------------------*/
-operand *operandFromLink (link *type)
-{
-    operand *op ;
-    
-    /* operand from link */
-    if ( ! type )
-       return NULL ;
-    
-    op = newOperand();
-    op->type = TYPE ;
-    op->operand.typeOperand = copyLinkChain(type);
-    return op;
+operand *
+operandFromLink (sym_link * type)
+{
+  operand *op;
+
+  /* operand from sym_link */
+  if (!type)
+    return NULL;
+
+  op = newOperand ();
+  op->type = TYPE;
+  op->operand.typeOperand = copyLinkChain (type);
+  return op;
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromLit - makes an operand from a literal value          */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromLit - makes an operand from a literal value          */
 /*-----------------------------------------------------------------*/
-operand *operandFromLit ( float i)
+operand *
+operandFromLit (double i)
 {
 {
-    return operandFromValue (valueFromLit (i));
+  return operandFromValue (valueFromLit (i));
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromAst - creates an operand from an ast                 */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* operandFromAst - creates an operand from an ast                 */
 /*-----------------------------------------------------------------*/
-operand *operandFromAst ( ast *tree )
+operand *
+operandFromAst (ast * tree,int lvl)
 {
 {
-    
-    if (! tree )
-       return NULL ;
-    
-    /* depending on type do */
-    switch (tree->type ) {     
-    case EX_OP : 
-       return ast2iCode (tree) ;    
-       break ;
-       
-    case EX_VALUE :
-       return operandFromValue(tree->opval.val) ;
-       break ;
-       
-    case EX_LINK :
-       return operandFromLink (tree->opval.lnk) ; 
+
+  if (!tree)
+    return NULL;
+
+  /* depending on type do */
+  switch (tree->type)
+    {
+    case EX_OP:
+      return ast2iCode (tree,lvl+1);
+      break;
+
+    case EX_VALUE:
+      return operandFromValue (tree->opval.val);
+      break;
+
+    case EX_LINK:
+      return operandFromLink (tree->opval.lnk);
+      break;
+
+    default:
+      assert (0);
     }
     }
-    
-    assert(0);
-    /*  Just to keep the comiler happy */
-    return (operand *)0;
+
+  /*  Just to keep the compiler happy */
+  return (operand *) 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* setOperandType - sets the operand's type to the given type      */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* setOperandType - sets the operand's type to the given type      */
 /*-----------------------------------------------------------------*/
-void setOperandType (operand *op, link *type)
-{
-    /* depending on the type of operand */
-    switch (op->type) {
-       
-    case VALUE :
-       op->operand.valOperand->etype = 
-           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 )) ;
-       else
-           werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
-                   "attempt to modify type of source");
-       return;
-       
+void
+setOperandType (operand * op, sym_link * type)
+{
+  /* depending on the type of operand */
+  switch (op->type)
+    {
+
+    case VALUE:
+      op->operand.valOperand->etype =
+        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));
+      else
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                "attempt to modify type of source");
+      return;
+
     case TYPE:
     case TYPE:
-       op->operand.typeOperand = copyLinkChain (type);
-       return ;
+      op->operand.typeOperand = copyLinkChain (type);
+      return;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* Get size in byte of ptr need to access an array                 */
+/*-----------------------------------------------------------------*/
+static int
+getArraySizePtr (operand * op)
+{
+  sym_link *ltype = operandType(op);
+
+  if(IS_PTR(ltype))
+    {
+      int size = getSize(ltype);
+      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:
+          if (GPTRSIZE > FPTRSIZE)
+            return (GPTRSIZE-1);
+          else
+            return (FPTRSIZE);
+
+        default:
+          return (FPTRSIZE);
+        }
+    }
+  return (FPTRSIZE);
+}
+
+/*-----------------------------------------------------------------*/
+/* perform "usual unary conversions"                               */
+/*-----------------------------------------------------------------*/
+#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);
+        }
+    }
+  return op;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* perform "usual binary conversions"                              */
+/*-----------------------------------------------------------------*/
+
+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, 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;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeValueAtAddress - generate intermeditate code for value  */
 /*                          at address                             */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeValueAtAddress - generate intermeditate code for value  */
 /*                          at address                             */
 /*-----------------------------------------------------------------*/
-operand *geniCodeRValue (operand *op, bool force)
-{
-    iCode *ic ;
-    link *type = operandType(op);
-    link *etype= getSpec(type);
-    
-    /* if this is an array & already */
-    /* an address then return this   */
-    if (IS_AGGREGATE(type) || 
-       (IS_PTR(type) && !force && !op->isaddr))
-       return operandFromOperand(op);
-        
-    /* if this is not an address then must be */
-    /* rvalue already so return this one      */
-    if (!op->isaddr)
-       return op ;
-    
-    /* if this is not a temp symbol then */
-    if (!IS_ITEMP(op) && 
-       !force        && 
-       !IN_FARSPACE(SPEC_OCLS(etype))) {
-       op = operandFromOperand(op);
-       op->isaddr = 0;
-       return op;
-    }
-    
-    if (IS_SPEC(type) && 
-       IS_TRUE_SYMOP(op) &&
-       !IN_FARSPACE(SPEC_OCLS(etype))) {
-       op = operandFromOperand(op);
-       op->isaddr = 0;
-       return op;
-    }
-
-    ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
-    if (IS_PTR(type) && op->isaddr && force) 
-       type = type->next;
-    
-    type = copyLinkChain(type);
-
-    IC_RESULT(ic) = newiTempOperand (type,1);
-    IC_RESULT(ic)->isaddr = 0;
+operand *
+geniCodeRValue (operand * op, bool force)
+{
+  iCode *ic;
+  sym_link *type = operandType (op);
+  sym_link *etype = getSpec (type);
+
+  /* if this is an array & already */
+  /* an address then return this   */
+  if (IS_AGGREGATE (type) ||
+      (IS_PTR (type) && !force && !op->isaddr))
+    return operandFromOperand (op);
+
+  /* if this is not an address then must be */
+  /* rvalue already so return this one      */
+  if (!op->isaddr)
+    return op;
+
+  /* if this is not a temp symbol then */
+  if (!IS_ITEMP (op) &&
+      !force &&
+      !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
+    {
+      op = operandFromOperand (op);
+      op->isaddr = 0;
+      return op;
+    }
+
+  if (IS_SPEC (type) &&
+      IS_TRUE_SYMOP (op) &&
+      (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
+      (options.model == MODEL_FLAT24) ))
+    {
+      op = operandFromOperand (op);
+      op->isaddr = 0;
+      return op;
+    }
+
+  ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
+  if (IS_PTR (type) && op->isaddr && force)
+    type = type->next;
+
+  type = copyLinkChain (type);
+
+  IC_RESULT (ic) = newiTempOperand (type, 1);
+  IC_RESULT (ic)->isaddr = 0;
+
 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
 
 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
 
-    /* if the right is a symbol */
-    if (op->type == SYMBOL)
-       IC_RESULT(ic)->operand.symOperand->args = 
-           op->operand.symOperand->args ;
-    ADDTOCHAIN(ic);
-    
-    return IC_RESULT(ic) ;
+  ADDTOCHAIN (ic);
+
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeCast - changes the value from one type to another       */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeCast - changes the value from one type to another       */
 /*-----------------------------------------------------------------*/
-operand *geniCodeCast (link *type, operand *op, bool implicit) 
-{
-    iCode *ic ;
-    link *optype ;
-    link *opetype = getSpec(optype = operandType(op));
-    link *restype ;
-    
-    /* one of them has size zero then error */
-    if (IS_VOID(optype)) {
-       werror(E_CAST_ZERO);
-       return op;
-    }
-
-    /* if the operand is already the desired type then do nothing */
-    if ( checkType (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)));
-          
-    /* if casting to some pointer type &&
-       the destination is not a generic pointer 
-       then give a warning : (only for implicit casts)*/
-    if (IS_PTR(optype) && implicit &&
-       (DCL_TYPE(optype) != DCL_TYPE(type)) && 
-       !IS_GENPTR(type)) {
-       werror(E_INCOMPAT_CAST);
-       werror(E_CONTINUE,"from type '");
-       printTypeChain(optype,stderr);fprintf(stderr,"' to type '");      
-       printTypeChain(type,stderr);fprintf(stderr,"'\n");
-    }
-
-    /* if they are the same size create an assignment */
-    if (getSize(type) == getSize(optype) && 
-       !IS_BITFIELD(type)               &&
-       !IS_FLOAT(type)                  &&
-       !IS_FLOAT(optype)                &&
-       ((IS_SPEC(type) && IS_SPEC(optype)) ||
-        (!IS_SPEC(type) && !IS_SPEC(optype)))) {
-
-       ic = newiCode('=',NULL,op);     
-       IC_RESULT(ic) = newiTempOperand(type,0);
-        SPIL_LOC(IC_RESULT(ic))  =
-            (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
-       IC_RESULT(ic)->isaddr = 0;
-    } else { 
-       ic = newiCode(CAST,operandFromLink(type),
-                     geniCodeRValue(op,FALSE));
-       
-       IC_RESULT(ic)= newiTempOperand(type,0);
-    }
-    
-    /* preserve the storage class & output class */
-    /* of the original variable                  */
-    restype = getSpec(operandType(IC_RESULT(ic)));
-    SPEC_SCLS(restype) = SPEC_SCLS(opetype);
-    SPEC_OCLS(restype) = SPEC_OCLS(opetype);
-    
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;
+static operand *
+geniCodeCast (sym_link * type, operand * op, bool implicit)
+{
+  iCode *ic;
+  sym_link *optype;
+  sym_link *opetype = getSpec (optype = operandType (op));
+  sym_link *restype;
+  int errors=0;
+
+  /* one of them has size zero then error */
+  if (IS_VOID (optype))
+    {
+      werror (E_CAST_ZERO);
+      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)));
+    }
+
+  /* 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 (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 (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 (errors) {
+    printFromToType (optype, type);
+  }
+
+  /* if they are the same size create an assignment */
+
+  /* This seems very dangerous to me, since there are several */
+  /* optimizations (for example, gcse) that don't notice the  */
+  /* cast hidden in this assignement and may simplify an      */
+  /* iCode to use the original (uncasted) operand.            */
+  /* Unfortunately, other things break when this cast is      */
+  /* made explicit. Need to fix this someday.                 */
+  /* -- EEP, 2004/01/21                                       */
+  if (getSize (type) == getSize (optype) &&
+      !IS_BITFIELD (type) &&
+      !IS_FLOAT (type) &&
+      !IS_FLOAT (optype) &&
+      !IS_FIXED (type) &&
+      !IS_FIXED (optype) &&
+      ((IS_SPEC (type) && IS_SPEC (optype)) ||
+       (!IS_SPEC (type) && !IS_SPEC (optype))))
+    {
+      ic = newiCode ('=', NULL, op);
+      IC_RESULT (ic) = newiTempOperand (type, 0);
+      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));
+
+      IC_RESULT (ic) = newiTempOperand (type, 0);
+    }
+
+  /* preserve the storage class & output class */
+  /* of the original variable                  */
+  restype = getSpec (operandType (IC_RESULT (ic)));
+  if (!IS_LITERAL(opetype) &&
+      !IS_BIT(opetype))
+    {
+      SPEC_SCLS (restype) = SPEC_SCLS (opetype);
+      SPEC_OCLS (restype) = SPEC_OCLS (opetype);
+    }
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeLabel - will create a Label                             */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeLabel - will create a Label                             */
 /*-----------------------------------------------------------------*/
-void geniCodeLabel (symbol *label)
+void
+geniCodeLabel (symbol * label)
 {
 {
-    iCode *ic;
-    
-    ic = newiCodeLabelGoto(LABEL,label);
-    ADDTOCHAIN(ic);
+  iCode *ic;
+
+  ic = newiCodeLabelGoto (LABEL, label);
+  ADDTOCHAIN (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeGoto  - will create a Goto                              */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeGoto  - will create a Goto                              */
 /*-----------------------------------------------------------------*/
-void geniCodeGoto (symbol *label)
+void
+geniCodeGoto (symbol * label)
 {
 {
-    iCode *ic;
-    
-    ic = newiCodeLabelGoto(GOTO,label);
-    ADDTOCHAIN(ic);
+  iCode *ic;
+
+  ic = newiCodeLabelGoto (GOTO, label);
+  ADDTOCHAIN (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeMultiply - gen intermediate code for multiplication     */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeMultiply - gen intermediate code for multiplication     */
 /*-----------------------------------------------------------------*/
-operand *geniCodeMultiply (operand *left, operand *right)
-{ 
-    iCode *ic ;
-    int p2 = 0;
-    link *resType ;
-    LRTYPE ;
-    
-    /* 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));
-        
-    resType = computeType (ltype,rtype) ;
-    left = geniCodeCast(resType,left,TRUE);
-    right= geniCodeCast(resType,right,TRUE);
-    
-    /* if the right is a literal & power of 2 */
-    /* then make it a left shift              */
-    if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
-       (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand)))) 
-       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;
-
-    }
-    IC_RESULT(ic) = newiTempOperand(resType,1);
-    
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;
+static operand *
+geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
+{
+  iCode *ic;
+  int p2 = 0;
+  sym_link *resType;
+  LRTYPE;
+
+  /* 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));
+
+  if (IS_LITERAL(retype)) {
+    p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
+  }
+
+  resType = usualBinaryConversions (&left, &right, resultType, '*');
+#if 1
+  rtype = operandType (right);
+  retype = getSpec (rtype);
+  ltype = operandType (left);
+  letype = getSpec (ltype);
+#endif
+
+  /* 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) && !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;
+
+    }
+  IC_RESULT (ic) = newiTempOperand (resType, 1);
+
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeDivision - gen intermediate code for division           */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeDivision - gen intermediate code for division           */
 /*-----------------------------------------------------------------*/
-operand *geniCodeDivision (operand *left, operand *right)
-{ 
-    iCode *ic ;
-    int p2 = 0;
-    link *resType;
-    link *rtype = operandType(right);
-    link *retype= getSpec(rtype);
-    link *ltype = operandType(left);
-    link *letype= getSpec(ltype);
-    
-    resType = computeType (ltype,rtype) ;
-    left = geniCodeCast(resType,left,TRUE);
-    right= geniCodeCast(resType,right,TRUE);
-    
-    /* if the right is a literal & power of 2 */
-    /* then make it a right shift             */
-    if (IS_LITERAL(retype) && 
-       !IS_FLOAT(letype)  &&
-       (p2 = powof2 ((unsigned long) 
-                     floatFromVal(right->operand.valOperand)))) 
-       ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
-    else {
-       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_RESULT(ic) = newiTempOperand(resType,0);
-    
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;
+static operand *
+geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
+{
+  iCode *ic;
+  int p2 = 0;
+  sym_link *resType;
+  sym_link *rtype = operandType (right);
+  sym_link *retype = getSpec (rtype);
+  sym_link *ltype = operandType (left);
+  sym_link *letype = getSpec (ltype);
+
+  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) &&
+      !IS_FIXED (letype) &&
+      IS_UNSIGNED(letype) &&
+      (p2 = powof2 ((TYPE_UDWORD)
+                    floatFromVal (right->operand.valOperand)))) {
+    ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
+  }
+  else
+    {
+      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_RESULT (ic) = newiTempOperand (resType, 0);
+
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 /*-----------------------------------------------------------------*/
 /* geniCodeModulus  - gen intermediate code for modulus            */
 /*-----------------------------------------------------------------*/
 }
 /*-----------------------------------------------------------------*/
 /* geniCodeModulus  - gen intermediate code for modulus            */
 /*-----------------------------------------------------------------*/
-operand *geniCodeModulus (operand *left, operand *right)
-{ 
-    iCode *ic ;
-    link *resType;
-    LRTYPE ;
-    
-    /* 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));
-    
-    resType = computeType (ltype,rtype) ;
-    left = geniCodeCast(resType,left,TRUE);
-    right= geniCodeCast(resType,right,TRUE);
-    
-    /* now they are the same size */
-    ic = newiCode('%',left,right);
-
-    /* if the size left or right > 1 then support routine */
-    if (getSize(ltype) > 1 || getSize(rtype) > 1)
-       ic->supportRtn = 1;
-    IC_RESULT(ic) = newiTempOperand(resType,0);
-    
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;
+static operand *
+geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
+{
+  iCode *ic;
+  sym_link *resType;
+  LRTYPE;
+
+  /* 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));
+
+  resType = usualBinaryConversions (&left, &right, resultType, '%');
+
+  /* now they are the same size */
+  ic = newiCode ('%', left, right);
+
+  /* if the size left or right > 1 then support routine */
+  if (getSize (ltype) > 1 || getSize (rtype) > 1)
+    ic->supportRtn = 1;
+  IC_RESULT (ic) = newiTempOperand (resType, 0);
+
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
 /*-----------------------------------------------------------------*/
-operand *geniCodePtrPtrSubtract (operand *left, operand *right)
+operand *
+geniCodePtrPtrSubtract (operand * left, operand * right)
 {
 {
-    iCode *ic ;
-    operand *result;
-    LRTYPE ;
-    
-    /* if they are both literals then */
-    if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
-       result = operandFromValue (valMinus(left->operand.valOperand,
-                                           right->operand.valOperand));
-       goto subtractExit;
+  iCode *ic;
+  operand *result;
+  LRTYPE;
+
+  /* if they are both literals then */
+  if (IS_LITERAL (letype) && IS_LITERAL (retype))
+    {
+      result = operandFromValue (valMinus (left->operand.valOperand,
+                                           right->operand.valOperand));
+      goto subtractExit;
     }
     }
-    
-    ic = newiCode('-',left,right);
-    
-    IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
-    ADDTOCHAIN(ic);
-    
- subtractExit:
-    return geniCodeDivision (result,
-                            operandFromLit(getSize(ltype->next)));   
+
+  ic = newiCode ('-', left, right);
+
+  IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
+  ADDTOCHAIN (ic);
+
+subtractExit:
+  if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
+    return result;
+  }
+
+  // should we really do this? is this ANSI?
+  return geniCodeDivision (result,
+                           operandFromLit (getSize (ltype->next)),
+                           FALSE);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSubtract - generates code for subtraction               */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSubtract - generates code for subtraction               */
 /*-----------------------------------------------------------------*/
-operand *geniCodeSubtract (operand *left, operand *right)
-{
-    iCode *ic ;
-    int isarray= 0;
-    link *resType;
-    LRTYPE ;
-    
-    /* if they both pointers then */
-    if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
-       (IS_PTR(rtype) || IS_ARRAY(rtype)))
-       return geniCodePtrPtrSubtract (left,right);
-    
-    /* if they are both literal then we know the result */
-    if (IS_LITERAL(letype) && IS_LITERAL(retype)
-       && left->isLiteral && right->isLiteral) 
-       return operandFromValue (valMinus(left->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)));
-       resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
-    }
-    else { /* make them the same size */
-       resType = computeType (ltype,rtype) ;
-       left = geniCodeCast(resType,left,TRUE);
-       right= geniCodeCast(resType,right,TRUE);    
-    }
-    
-    ic = newiCode('-',left,right);
-    
-    IC_RESULT(ic)= newiTempOperand(resType,1);
-    IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
-
-    /* if left or right is a float */
-    if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
-       ic->supportRtn = 1;
-
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;
+static operand *
+geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
+{
+  iCode *ic;
+  int isarray = 0;
+  sym_link *resType;
+  LRTYPE;
+
+  /* if they both pointers then */
+  if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
+      (IS_PTR (rtype) || IS_ARRAY (rtype)))
+    return geniCodePtrPtrSubtract (left, right);
+
+  /* if they are both literal then we know the result */
+  if (IS_LITERAL (letype) && IS_LITERAL (retype)
+      && left->isLiteral && right->isLiteral)
+    return operandFromValue (valMinus (left->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) ?
+                                  RESULT_TYPE_INT :
+                                  RESULT_TYPE_CHAR);
+      resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
+    }
+  else
+    {                           /* make them the same size */
+      resType = usualBinaryConversions (&left, &right, resultType, '-');
+    }
+
+  ic = newiCode ('-', left, right);
+
+  IC_RESULT (ic) = newiTempOperand (resType, 1);
+  IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
+
+  /* if left or right is a float */
+  if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
+      || IS_FIXED (ltype) || IS_FIXED (rtype))
+    ic->supportRtn = 1;
+
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeAdd - generates iCode for addition                      */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeAdd - generates iCode for addition                      */
 /*-----------------------------------------------------------------*/
-operand *geniCodeAdd (operand *left, operand *right )
-{
-    iCode *ic ;
-    link *resType ;
-    operand *size ;
-    int isarray = 0;
-    LRTYPE ;
-
-    /* if left is an array then array access */
-    if (IS_ARRAY(ltype)) 
-       return geniCodeArray (left,right);           
-    
-    /* if the right side is LITERAL zero */
-    /* return the left side              */
-    if (IS_LITERAL(retype) && right->isLiteral && !floatFromVal(valFromType(retype)))
-       return left;
-    
-    /* if left is literal zero return right */
-    if (IS_LITERAL(letype) && left->isLiteral && !floatFromVal(valFromType(letype)))
-       return right ;
-    
-    /* if left is an array or pointer then size */
-    if (IS_PTR(ltype)) {    
-       
-       isarray = left->isaddr;
-       size = 
-           operandFromLit(getSize(ltype->next));
-       right = geniCodeMultiply (right ,size);
-       resType = copyLinkChain(ltype);
-    }
-    else { /* make them the same size */
-       resType = computeType (ltype,rtype) ;
-       left = geniCodeCast(resType,left,TRUE);
-       right= geniCodeCast(resType,right,TRUE);
-    }
-    
-    /* 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)));
-    
-    ic = newiCode('+',left,right);
-    
-    IC_RESULT(ic) = newiTempOperand(resType,1);
-    IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
-
-    /* if left or right is a float then support
-       routine */
-    if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
-       ic->supportRtn = 1;
-
-    ADDTOCHAIN(ic);
-    
-    return IC_RESULT(ic) ;
-    
-}
-
-/*-----------------------------------------------------------------*/
-/* aggrToPtr - changes an aggregate to pointer to an aggregate     */
-/*-----------------------------------------------------------------*/
-link *aggrToPtr ( link *type, bool force)
-{
-    link *etype ;
-    link *ptype ;
-
-    
-    if (IS_PTR(type) && !force)
-       return type;
-
-    etype = getSpec(type);
-    ptype = newLink();
-
-    ptype->next = type;
-    /* if the output class is generic */
-    if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
-       DCL_PTR_CONST(ptype) = port->mem.code_ro;
-
-    /* if the variable was declared a constant */
-    /* then the pointer points to a constant */
-    if (IS_CONSTANT(etype) )
-       DCL_PTR_CONST(ptype) = 1;
-
-    /* the variable was volatile then pointer to volatile */
-    if (IS_VOLATILE(etype))
-       DCL_PTR_VOLATILE(ptype) = 1;
-    return ptype; 
+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 (rtype)))
+    return left;
+
+  /* if left is literal zero return right */
+  if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
+    return right;
+
+  /* if left is a pointer then size */
+  if (IS_PTR (ltype) || IS_ARRAY(ltype))
+    {
+      isarray = left->isaddr;
+      // there is no need to multiply with 1
+      if (getSize (ltype->next) != 1)
+        {
+          size  = operandFromLit (getSize (ltype->next));
+          SPEC_USIGN (getSpec (operandType (size))) = 1;
+          indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
+          right = geniCodeMultiply (right,
+                                    size,
+                                    (getArraySizePtr(left) >= INTSIZE) ?
+                                      RESULT_TYPE_INT :
+                                      RESULT_TYPE_CHAR);
+          /* Even if right is a 'unsigned char',
+             the result will be a 'signed int' due to the promotion rules.
+             It doesn't make sense when accessing arrays, so let's fix it here: */
+          if (indexUnsigned)
+            SPEC_USIGN (getSpec (operandType (right))) = 1;
+        }
+      resType = copyLinkChain (ltype);
+    }
+  else
+    { // make them the same size
+      resType = usualBinaryConversions (&left, &right, resultType, '+');
+    }
+
+  /* if they are both literals then we know */
+  if (IS_LITERAL (letype) && IS_LITERAL (retype)
+      && left->isLiteral && right->isLiteral)
+    return operandFromValue (valPlus (valFromType (ltype),
+                                      valFromType (rtype)));
+
+  ic = newiCode ('+', left, right);
+
+  IC_RESULT (ic) = newiTempOperand (resType, 1);
+  IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
+
+  /* if left or right is a float then support
+     routine */
+  if (IS_FLOAT (ltype) || IS_FLOAT (rtype)
+      || IS_FIXED (ltype) || IS_FIXED (rtype))
+    ic->supportRtn = 1;
+
+  ADDTOCHAIN (ic);
+
+  return IC_RESULT (ic);
+
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
-/* geniCodeArray2Ptr - array to pointer                            */
+/* aggrToPtr - changes an "aggregate" to a "pointer to aggregate"  */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-operand *geniCodeArray2Ptr (operand *op)
+sym_link *
+aggrToPtr (sym_link * type, bool force)
 {
 {
-    link *optype = operandType(op);
-    link *opetype = getSpec(optype);
+  sym_link *etype;
+  sym_link *ptype;
 
 
-    /* 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 (IS_PTR (type) && !force)
+    return type;
 
 
-    
-    /* if the variable was declared a constant */
-    /* then the pointer points to a constant */
-    if (IS_CONSTANT(opetype) )
-       DCL_PTR_CONST(optype) = 1;
+  etype = getSpec (type);
+  ptype = newLink (DECLARATOR);
 
 
-    /* the variable was volatile then pointer to volatile */
-    if (IS_VOLATILE(opetype))
-       DCL_PTR_VOLATILE(optype) = 1;
-    op->isaddr = 0;
-    return op;
+  ptype->next = type;
+
+  /* set the pointer depending on the storage class */
+  DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
+  return ptype;
+}
+
+/*------------------------------------------------------------------*/
+/* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
+/*------------------------------------------------------------------*/
+int
+aggrToPtrDclType (sym_link * type, bool force)
+{
+  if (IS_PTR (type) && !force)
+    return DCL_TYPE (type);
+
+  /* return the pointer depending on the storage class */
+  return PTR_TYPE (SPEC_OCLS (getSpec (type)));
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
-/* geniCodeArray - array access                                    */
+/* geniCodeArray2Ptr - array to pointer                            */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-operand *geniCodeArray (operand *left,operand *right)
+static operand *
+geniCodeArray2Ptr (operand * op)
 {
 {
-    iCode *ic;
-    link *ltype = operandType(left);
-    
-    if (IS_PTR(ltype)) {
-       if (IS_PTR(ltype->next) && left->isaddr)
-           left = geniCodeRValue(left,FALSE);
-       return geniCodeDerefPtr(geniCodeAdd(left,right));
-    }
+  sym_link *optype = operandType (op);
+  sym_link *opetype = getSpec (optype);
+
+  /* set the pointer depending on the storage class */
+  DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
+
+  op->isaddr = 0;
+  return op;
+}
 
 
-    /* array access */
-    right = geniCodeMultiply(right,
-                            operandFromLit(getSize(ltype->next)));
 
 
-    /* we can check for limits here */
-    if (isOperandLiteral(right) &&
-       IS_ARRAY(ltype)         &&
-       DCL_ELEM(ltype)         &&
-       (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
-       werror(E_ARRAY_BOUND);
-       right = operandFromLit(0);
+/*-----------------------------------------------------------------*/
+/* geniCodeArray - array access                                    */
+/*-----------------------------------------------------------------*/
+static operand *
+geniCodeArray (operand * left, operand * right, int lvl)
+{
+  iCode *ic;
+  operand *size;
+  sym_link *ltype = operandType (left);
+  bool indexUnsigned;
+
+  if (IS_PTR (ltype))
+    {
+      if (IS_PTR (ltype->next) && left->isaddr)
+        {
+          left = geniCodeRValue (left, FALSE);
+        }
+
+      return geniCodeDerefPtr (geniCodeAdd (left,
+                                            right,
+                                            (getArraySizePtr(left) >= INTSIZE) ?
+                                              RESULT_TYPE_INT :
+                                              RESULT_TYPE_CHAR,
+                                            lvl),
+                               lvl);
     }
     }
+  size = operandFromLit (getSize (ltype->next));
+  SPEC_USIGN (getSpec (operandType (size))) = 1;
+  indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
+  right = geniCodeMultiply (right,
+                            size,
+                            (getArraySizePtr(left) >= INTSIZE) ?
+                              RESULT_TYPE_INT :
+                              RESULT_TYPE_CHAR);
+  /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
+     It doesn't make sense when accessing arrays, so let's fix it here: */
+  if (indexUnsigned)
+    SPEC_USIGN (getSpec (operandType (right))) = 1;
+  /* we can check for limits here */
+  /* already done in SDCCast.c
+  if (isOperandLiteral (right) &&
+      IS_ARRAY (ltype) &&
+      DCL_ELEM (ltype) &&
+      (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
+    {
+      werror (W_IDX_OUT_OF_BOUNDS,
+              (int) operandLitValue (right) / getSize (ltype->next),
+              DCL_ELEM (ltype));
+    }
+  */
+
+  ic = newiCode ('+', left, right);
 
 
-    ic = newiCode('+',left,right);    
+  IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
+                                      !IS_AGGREGATE (ltype->next) &&
+                                      !IS_PTR (ltype->next))
+                                     ? ltype : ltype->next), 0);
 
 
-    IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) && 
-                                     !IS_AGGREGATE(ltype->next) &&
-                                     !IS_PTR(ltype->next))
-                                    ? ltype : ltype->next),0);
+  if (!IS_AGGREGATE (ltype->next))
+    {
+      IC_RESULT (ic)->isaddr = 1;
+      IC_RESULT (ic)->aggr2ptr = 1;
+    }
+  ADDTOCHAIN (ic);
 
 
-    IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
-    ADDTOCHAIN(ic);
-    return IC_RESULT(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)
+operand *
+geniCodeStruct (operand * left, operand * right, bool islval)
 {
 {
-    iCode *ic ;
-    link *type = operandType(left);
-    link *etype = getSpec(type);
-    link *retype ;
-    symbol *element = getStructElement(SPEC_STRUCT(etype), 
-                                      right->operand.symOperand);
-    
-    /* add the offset */
-    ic = newiCode('+',left,operandFromLit(element->offset));
-    
-    IC_RESULT(ic) = newiTempOperand(element->type,0);
+  iCode *ic;
+  sym_link *type = operandType (left);
+  sym_link *etype = getSpec (type);
+  sym_link *retype;
+  symbol *element = getStructElement (SPEC_STRUCT (etype),
+                                      right->operand.symOperand);
+
+  wassert(IS_SYMOP(right));
+
+  /* add the offset */
+  ic = newiCode ('+', left, operandFromLit (element->offset));
+
+  IC_RESULT (ic) = newiTempOperand (element->type, 0);
 
 
-    /* preserve the storage & output class of the struct */
-    /* as well as the volatile attribute */
-    retype = getSpec(operandType(IC_RESULT(ic)));
-    SPEC_SCLS(retype) = SPEC_SCLS(etype);
-    SPEC_OCLS(retype) = SPEC_OCLS(etype);
-    SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);    
+  /* preserve the storage & output class of the struct */
+  /* as well as the volatile attribute */
+  retype = getSpec (operandType (IC_RESULT (ic)));
+  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));
+  if (IS_PTR (element->type))
+    setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
 
 
-    
-    ADDTOCHAIN(ic);
-    return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
+  IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
+
+  ADDTOCHAIN (ic);
+  return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePostInc - generate int code for Post increment          */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePostInc - generate int code for Post increment          */
 /*-----------------------------------------------------------------*/
-operand *geniCodePostInc (operand *op)
+operand *
+geniCodePostInc (operand * op)
 {
 {
-    iCode *ic ;
-    operand *rOp ;
-    link *optype = operandType(op);
-    operand *result ;
-    operand *rv = (IS_ITEMP(op) ? 
-                  geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
-                  op);            
-    link *rvtype = operandType(rv);    
-    int size = 0;
-    
-    /* if this is not an address we have trouble */
-    if ( ! op->isaddr ) {
-       werror (E_LVALUE_REQUIRED,"++");
-       return op ;
+  iCode *ic;
+  operand *rOp;
+  sym_link *optype = operandType (op);
+  operand *result;
+  operand *rv = (IS_ITEMP (op) ?
+                 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+                 op);
+  sym_link *rvtype = operandType (rv);
+  int size = 0;
+
+  /* if this is not an address we have trouble */
+  if (!op->isaddr)
+    {
+      werror (E_LVALUE_REQUIRED, "++");
+      return op;
     }
     }
-    
-    rOp = newiTempOperand(rvtype,0);
-    rOp->noSpilLoc = 1;
 
 
-    if (IS_ITEMP(rv))
-       rv->noSpilLoc = 1;
+  rOp = newiTempOperand (rvtype, 0);
+  OP_SYMBOL(rOp)->noSpilLoc = 1;
+
+  if (IS_ITEMP (rv))
+    OP_SYMBOL(rv)->noSpilLoc = 1;
+
+  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, 0);
 
 
-    geniCodeAssign(rOp,rv,0);
-   
-    size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
-    ic = newiCode('+',rv,operandFromLit(size));          
-    IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
-    ADDTOCHAIN(ic);
+  return rOp;
 
 
-    geniCodeAssign(op,result,0);
-    
-    return rOp;
-    
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePreInc - generate code for preIncrement                 */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePreInc - generate code for preIncrement                 */
 /*-----------------------------------------------------------------*/
-operand *geniCodePreInc (operand *op)
+operand *
+geniCodePreInc (operand * op, bool lvalue)
 {
 {
-    iCode *ic ;
-    link *optype = operandType(op);    
-    operand *rop = (IS_ITEMP(op) ? 
-                   geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
-                   op);
-    link *roptype = operandType(rop);
-    operand *result;
-    int size = 0;
-    
-    if ( ! op->isaddr ) {
-       werror(E_LVALUE_REQUIRED,"++");
-       return op ;
+  iCode *ic;
+  sym_link *optype = operandType (op);
+  operand *rop = (IS_ITEMP (op) ?
+                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+                  op);
+  sym_link *roptype = operandType (rop);
+  operand *result;
+  int size = 0;
+
+  if (!op->isaddr)
+    {
+      werror (E_LVALUE_REQUIRED, "++");
+      return op;
     }
 
     }
 
-
-    size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
-    ic = newiCode('+',rop,operandFromLit(size));
-    IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
-    ADDTOCHAIN(ic);
-
-    
-    return geniCodeAssign(op,result,0) ;
+  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);
+
+  (void) geniCodeAssign (op, result, 0, 0);
+  if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
+    return op;
+  else
+    return result;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePostDec - generates code for Post decrement             */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePostDec - generates code for Post decrement             */
 /*-----------------------------------------------------------------*/
-operand *geniCodePostDec (operand *op)
+operand *
+geniCodePostDec (operand * op)
 {
 {
-    iCode *ic ;
-    operand *rOp ;
-    link *optype = operandType(op);
-    operand *result ;
-    operand *rv = (IS_ITEMP(op) ? 
-                  geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
-                  op);            
-    link *rvtype = operandType(rv);    
-    int size = 0;
-    
-    /* if this is not an address we have trouble */
-    if ( ! op->isaddr ) {
-       werror (E_LVALUE_REQUIRED,"++");
-       return op ;
+  iCode *ic;
+  operand *rOp;
+  sym_link *optype = operandType (op);
+  operand *result;
+  operand *rv = (IS_ITEMP (op) ?
+                 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
+                 op);
+  sym_link *rvtype = operandType (rv);
+  int size = 0;
+
+  /* if this is not an address we have trouble */
+  if (!op->isaddr)
+    {
+      werror (E_LVALUE_REQUIRED, "--");
+      return op;
     }
     }
-    
-    rOp = newiTempOperand(rvtype,0);
-    rOp->noSpilLoc = 1;
 
 
-    if (IS_ITEMP(rv))
-       rv->noSpilLoc = 1;
+  rOp = newiTempOperand (rvtype, 0);
+  OP_SYMBOL(rOp)->noSpilLoc = 1;
+
+  if (IS_ITEMP (rv))
+    OP_SYMBOL(rv)->noSpilLoc = 1;
 
 
-    geniCodeAssign(rOp,rv,0);
-   
-    size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
-    ic = newiCode('-',rv,operandFromLit(size));          
-    IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
-    ADDTOCHAIN(ic);
+  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, 0);
+
+  return rOp;
 
 
-    geniCodeAssign(op,result,0);
-    
-    return rOp;
-    
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePreDec - generate code for pre  decrement               */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodePreDec - generate code for pre  decrement               */
 /*-----------------------------------------------------------------*/
-operand *geniCodePreDec (operand *op)
-{  
-    iCode *ic ;
-    link *optype = operandType(op);    
-    operand *rop = (IS_ITEMP(op) ? 
-                   geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
-                   op);
-    link *roptype = operandType(rop);
-    operand *result;
-    int size = 0;
-    
-    if ( ! op->isaddr ) {
-       werror(E_LVALUE_REQUIRED,"++");
-       return op ;
+operand *
+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);
+  sym_link *roptype = operandType (rop);
+  operand *result;
+  int size = 0;
+
+  if (!op->isaddr)
+    {
+      werror (E_LVALUE_REQUIRED, "--");
+      return op;
     }
 
     }
 
-
-    size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
-    ic = newiCode('-',rop,operandFromLit(size));
-    IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
-    ADDTOCHAIN(ic);
-
-    
-    return geniCodeAssign(op,result,0) ;
+  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);
+
+  (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, link *resType)
+operand *
+geniCodeBitwise (operand * left, operand * right,
+                 int oper, sym_link * resType)
 {
 {
-    iCode *ic;   
-    
-    left = geniCodeCast(resType,left,TRUE);
-    right= geniCodeCast(resType,right,TRUE);
-    
-    ic = newiCode(oper,left,right);
-    IC_RESULT(ic) = newiTempOperand(resType,0);
-    
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;
+  iCode *ic;
+
+  left = geniCodeCast (resType, left, TRUE);
+  right = geniCodeCast (resType, right, TRUE);
+
+  ic = newiCode (oper, left, right);
+  IC_RESULT (ic) = newiTempOperand (resType, 0);
+
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeAddressOf - gens icode for '&' address of operator      */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeAddressOf - gens icode for '&' address of operator      */
 /*-----------------------------------------------------------------*/
-operand *geniCodeAddressOf (operand *op) 
+operand *
+geniCodeAddressOf (operand * op)
 {
 {
-    iCode *ic;
-    link *p ;
-    link *optype = operandType(op);
-    link *opetype= getSpec(optype);
-    
-    /* lvalue check already done in decorateType */
-    /* this must be a lvalue */
+  iCode *ic;
+  sym_link *p;
+  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)) { */
 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
-/*     werror (E_LVALUE_REQUIRED,"&"); */
-/*     return op; */
+/*  werror (E_LVALUE_REQUIRED,"&"); */
+/*  return op; */
 /*     } */
 /*     } */
-    
-    p = newLink();
-    p->class = 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;
-    
-    p->next = copyLinkChain(optype);
-    
-    /* if already a temp */
-    if (IS_ITEMP(op)) {
-       setOperandType (op,p);     
-       op->isaddr= 0;
-       return op;
-    }
-    
-    /* other wise 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);
+
+  p = newLink (DECLARATOR);
+
+  /* set the pointer depending on the storage class */
+  DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
+
+  p->next = copyLinkChain (optype);
+
+  /* if already a temp */
+  if (IS_ITEMP (op))
+    {
+      setOperandType (op, p);
+      op->isaddr = 0;
+      return op;
+    }
+
+  /* other wise 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 */
 /*-----------------------------------------------------------------*/
 }
 /*-----------------------------------------------------------------*/
 /* setOClass - sets the output class depending on the pointer type */
 /*-----------------------------------------------------------------*/
-void setOClass (link *ptr, link *spec)
+void
+setOClass (sym_link * ptr, sym_link * spec)
 {
 {
-    switch (DCL_TYPE(ptr)) {
+  switch (DCL_TYPE (ptr))
+    {
     case POINTER:
     case POINTER:
-       SPEC_OCLS(spec) = data ;
-       break ;
-       
+      SPEC_OCLS (spec) = data;
+      break;
+
     case GPOINTER:
     case GPOINTER:
-       SPEC_OCLS(spec) = generic;
-       break;
-       
+      SPEC_OCLS (spec) = generic;
+      break;
+
     case FPOINTER:
     case FPOINTER:
-       SPEC_OCLS(spec) = xdata ;
-       break ;
-       
+      SPEC_OCLS (spec) = xdata;
+      break;
+
     case CPOINTER:
     case CPOINTER:
-       SPEC_OCLS(spec) = code ;
-       break ;  
-       
+      SPEC_OCLS (spec) = code;
+      break;
+
     case IPOINTER:
     case IPOINTER:
-       SPEC_OCLS(spec) = idata;
-       break;
+      SPEC_OCLS (spec) = idata;
+      break;
 
     case PPOINTER:
 
     case PPOINTER:
-       SPEC_OCLS(spec) = xstack;
-       break;
+      SPEC_OCLS (spec) = xstack;
+      break;
 
     case EEPPOINTER:
 
     case EEPPOINTER:
-       SPEC_OCLS(spec) = eeprom;
-       break;
+      SPEC_OCLS (spec) = eeprom;
+      break;
 
     default:
 
     default:
-       break;
+      break;
 
     }
 }
 
     }
 }
@@ -2013,1057 +2858,1641 @@ void setOClass (link *ptr, link *spec)
 /*-----------------------------------------------------------------*/
 /* geniCodeDerefPtr - dereference pointer with '*'                 */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* geniCodeDerefPtr - dereference pointer with '*'                 */
 /*-----------------------------------------------------------------*/
-operand *geniCodeDerefPtr (operand *op)
-{    
-    link *rtype , *retype ;
-    link *optype = operandType(op);  
+operand *
+geniCodeDerefPtr (operand * op,int lvl)
+{
+  sym_link *rtype, *retype;
+  sym_link *optype = operandType (op);
+
+  // if this is an array then array access
+  if (IS_ARRAY (optype)) {
+    // don't worry, this will be optimized out later
+    return geniCodeArray (op, operandFromLit (0), lvl);
+  }
 
 
-    /* if this is a pointer then generate the rvalue */
-    if (IS_PTR(optype)) {
-       if (IS_TRUE_SYMOP(op)) {
-           op->isaddr = 1;
-           op = geniCodeRValue(op,TRUE);
-       }
-       else    
-           op = geniCodeRValue(op,TRUE);       
+  // just in case someone screws up
+  wassert (IS_PTR (optype));
+
+  if (IS_TRUE_SYMOP (op))
+    {
+      op->isaddr = 1;
+      op = geniCodeRValue (op, TRUE);
     }
     }
-    
-    /* now get rid of the pointer part */
-    if (lvaluereq && IS_ITEMP(op) )
+
+  /* now get rid of the pointer part */
+  if (isLvaluereq(lvl) && IS_ITEMP (op))
     {
     {
-       retype = getSpec(rtype = copyLinkChain(optype)) ;
+      retype = getSpec (rtype = copyLinkChain (optype));
     }
     }
-    else
+  else
     {
     {
-       retype = getSpec(rtype = copyLinkChain(optype->next)) ;
+      retype = getSpec (rtype = copyLinkChain (optype->next));
+      /* outputclass needs 2b updated */
+      setOClass (optype, retype);
     }
     }
-    
-    /* if this is a pointer then outputclass needs 2b updated */
-    if (IS_PTR(optype)) 
-       setOClass(optype,retype);    
-        
-    op->isGptr = IS_GENPTR(optype);
 
 
-    /* if the pointer was declared as a constant */
-    /* then we cannot allow assignment to the derefed */
-    if (IS_PTR_CONST(optype))
-       SPEC_CONST(retype) = 1;
-    
-    op->isaddr = (IS_PTR(rtype)    ||
-                 IS_STRUCT(rtype) || 
-                 IS_INT(rtype)    ||
-                 IS_CHAR(rtype)   ||
-                 IS_FLOAT(rtype) );
+  op->isGptr = IS_GENPTR (optype);
+
+  op->isaddr = (IS_PTR (rtype) ||
+                IS_STRUCT (rtype) ||
+                IS_INT (rtype) ||
+                IS_CHAR (rtype) ||
+                IS_FLOAT (rtype) ||
+                IS_FIXED (rtype));
+
+  if (!isLvaluereq(lvl))
+    op = geniCodeRValue (op, TRUE);
 
 
-    if (!lvaluereq)
-       op = geniCodeRValue(op,TRUE);
+  setOperandType (op, rtype);
 
 
-    setOperandType(op,rtype);
-    
-    return op;    
+  return op;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeUnaryMinus - does a unary minus of the operand          */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeUnaryMinus - does a unary minus of the operand          */
 /*-----------------------------------------------------------------*/
-operand *geniCodeUnaryMinus (operand *op)
+operand *
+geniCodeUnaryMinus (operand * op)
 {
 {
-    iCode *ic ;
-    link *optype = operandType(op);
-    
-    if (IS_LITERAL(optype))
-       return operandFromLit(- floatFromVal(op->operand.valOperand));
-    
-    ic = newiCode(UNARYMINUS,op,NULL);
-    IC_RESULT(ic) = newiTempOperand(optype,0);
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic);
+  iCode *ic;
+  sym_link *optype = operandType (op);
+
+  if (IS_LITERAL (optype))
+    return operandFromLit (-floatFromVal (op->operand.valOperand));
+
+  ic = newiCode (UNARYMINUS, op, NULL);
+  IC_RESULT (ic) = newiTempOperand (optype, 0);
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeLeftShift - gen i code for left shift                   */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeLeftShift - gen i code for left shift                   */
 /*-----------------------------------------------------------------*/
-operand *geniCodeLeftShift (operand *left, operand *right)
-{ 
-    iCode *ic;
-    link *ltype = operandType(left);
-    
-    ic = newiCode(LEFT_OP,left,right);
-    IC_RESULT(ic) = newiTempOperand(ltype,0);
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;  
+operand *
+geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
+{
+  iCode *ic;
+  sym_link *resType;
+
+  ic = newiCode (LEFT_OP, left, right);
+
+  resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
+  IC_RESULT (ic) = newiTempOperand (resType, 0);
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeRightShift - gen i code for right shift                 */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeRightShift - gen i code for right shift                 */
 /*-----------------------------------------------------------------*/
-operand *geniCodeRightShift (operand *left, operand *right)
-{ 
-    iCode *ic;
-    link *ltype = operandType(left);
-    
-    ic = newiCode(RIGHT_OP,left,right);
-    IC_RESULT(ic) = newiTempOperand(ltype,0);
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;  
-}
-
-#ifdef __BORLANDC__
-#define LONG_LONG __int64
-#else
-#define LONG_LONG long long
-#endif
+operand *
+geniCodeRightShift (operand * left, operand * right)
+{
+  iCode *ic;
+
+  ic = newiCode (RIGHT_OP, left, right);
+  IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
+}
 
 /*-----------------------------------------------------------------*/
 /* geniCodeLogic- logic code                                       */
 /*-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------*/
 /* geniCodeLogic- logic code                                       */
 /*-----------------------------------------------------------------*/
-operand *geniCodeLogic (operand *left, operand *right, int op )
+static operand *
+geniCodeLogic (operand * left, operand * right, int op)
 {
 {
-    iCode *ic ;
-    link *ctype; 
-    link *rtype = operandType(right);
-    link *ltype = operandType(left);
-    
-    /* left is integral type and right is literal then
-       check if the literal value is within bounds */
-    if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
-       int nbits = bitsForType(ltype);
-       long v = operandLitValue(right);
+  iCode *ic;
+  sym_link *ctype;
+  sym_link *rtype = operandType (right);
+  sym_link *ltype = operandType (left);
+
+  /* left is integral type and right is literal then
+     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);
+    }
 
 
-       if (v > ((LONG_LONG) 1 << nbits) && v > 0)
-           werror(W_CONST_RANGE," compare operation ");
+  /* 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 = computeType(ltype,rtype);                        
-    left = geniCodeCast(ctype,left,TRUE);
-    right= geniCodeCast(ctype,right,TRUE);
+  ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
 
 
-    ic = newiCode(op,left,right);
-    IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
+  ic = newiCode (op, left, right);
+  IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
 
 
-    /* if comparing anything greater than one byte
-       and not a '==' || '!=' || '&&' || '||' (these
-       will be inlined */
-    if (getSize(ctype) > 1 && 
-       op != EQ_OP        && 
-       op != NE_OP        &&
-       op != AND_OP       &&
-       op != OR_OP        )
-       ic->supportRtn = 1;
+  /* if comparing float
+     and not a '==' || '!=' || '&&' || '||' (these
+     will be inlined */
+  if (IS_FLOAT(ctype) &&
+      op != EQ_OP &&
+      op != NE_OP &&
+      op != AND_OP &&
+      op != OR_OP)
+   ic->supportRtn = 1;
 
 
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic);
+  /* if comparing a fixed type use support functions */
+  if (IS_FIXED(ctype))
+    ic->supportRtn = 1;
+
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
-/* geniCodeUnary - for a a generic unary operation                 */
+/* geniCodeLogicAndOr - && || operations                           */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-operand *geniCodeUnary (operand *op, int oper )
+static operand *
+geniCodeLogicAndOr (ast *tree, int lvl)
 {
 {
-    iCode *ic = newiCode (oper,op,NULL);
-    
-    IC_RESULT(ic)= newiTempOperand(operandType(op),0);
-    ADDTOCHAIN(ic);
-    return IC_RESULT(ic) ;
+  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 = (SPEC_NOUN(tree->ftype) == V_BIT) ? 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)
+{
+  iCode *ic = newiCode (oper, op, NULL);
+
+  IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
+  ADDTOCHAIN (ic);
+  return IC_RESULT (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeConditional - geniCode for '?' ':' operation            */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeConditional - geniCode for '?' ':' operation            */
 /*-----------------------------------------------------------------*/
-operand *geniCodeConditional (ast *tree)
-{
-    iCode *ic ;
-    symbol *falseLabel = newiTempLabel(NULL);
-    symbol *exitLabel  = newiTempLabel(NULL);
-    operand *cond = ast2iCode(tree->left);
-    operand *true, *false , *result;
-    
-    ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
-                          NULL,falseLabel);
-    ADDTOCHAIN(ic);
-    
-    true = ast2iCode(tree->right->left);
-    
-    /* move the value to a new Operand */
-    result = newiTempOperand(operandType(true),0);
-    geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
-    
-    /* generate an unconditional goto */
-    geniCodeGoto(exitLabel);
-    
-    /* now for the right side */
-    geniCodeLabel(falseLabel);
-    
-    false = ast2iCode(tree->right->right);
-    geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
-    
-    /* create the exit label */
-    geniCodeLabel(exitLabel);
-    
-    return result ;
+operand *
+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;
+
+  ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
+                          NULL, falseLabel);
+  ADDTOCHAIN (ic);
+
+  true = ast2iCode (tree->right->left,lvl+1);
+
+  /* move the value to a new Operand */
+  result = newiTempOperand (tree->right->ftype, 0);
+  geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
+
+  /* generate an unconditional goto */
+  geniCodeGoto (exitLabel);
+
+  /* now for the right side */
+  geniCodeLabel (falseLabel);
+
+  false = ast2iCode (tree->right->right,lvl+1);
+  geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
+
+  /* create the exit label */
+  geniCodeLabel (exitLabel);
+
+  return result;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeAssign - generate code for assignment                   */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeAssign - generate code for assignment                   */
 /*-----------------------------------------------------------------*/
-operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
-{
-    iCode *ic ;
-    link *ltype = operandType(left);
-    link *rtype = operandType(right);
-    
-    if (!left->isaddr && !IS_ITEMP(left)) {
-       werror(E_LVALUE_REQUIRED,"assignment");
-       return left;
-    }
-       
-    /* 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)) {
-       int nbits = bitsForType(ltype);
-       long v = operandLitValue(right);
-
-       if (v > ((LONG_LONG)1 << nbits) && v > 0)
-           werror(W_CONST_RANGE," = operation");
-    }
-
-    /* if the left & right type don't exactly match */
-    /* if pointer set then make sure the check is
-       done with the type & not the pointer */
-    /* then cast rights type to left */   
-
-    /* first check the type for pointer assignement */
-    if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
-       checkType(ltype,rtype)<0) {
-       if (checkType(ltype->next,rtype) < 0)
-           right = geniCodeCast(ltype->next,right,TRUE);
-    } else
-       if (checkType(ltype,rtype) < 0 )
-           right = geniCodeCast(ltype,right,TRUE);
-
-    /* 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 */
-    if (IS_TRUE_SYMOP(left) && 
-       !isOperandVolatile(left,FALSE) &&
-       isOperandGlobal(left)) {
-       symbol *sym = NULL;
-
-       if (IS_TRUE_SYMOP(right))
-           sym = OP_SYMBOL(right);
-       ic = newiCode('=',NULL,right);
-       IC_RESULT(ic) = right = newiTempOperand(ltype,0);       
-       SPIL_LOC(right)  = sym ;
-       ADDTOCHAIN(ic);
-    }
-    
-    ic = newiCode('=',NULL,right);
-    IC_RESULT(ic) = left;
-    ADDTOCHAIN(ic);    
-
-    /* if left isgptr flag is set then support
-       routine will be required */
-    if (left->isGptr)
-       ic->supportRtn = 1;
-
-    ic->nosupdate = nosupdate;
-    return left;
+operand *
+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) || strictLval))
+    {
+      werror (E_LVALUE_REQUIRED, "assignment");
+      return left;
+    }
+
+  /* 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))
+    {
+      checkConstantRange(ltype,
+                         OP_VALUE(right), "= operation", 0);
+    }
+
+  /* if the left & right type don't exactly match */
+  /* if pointer set then make sure the check is
+     done with the type & not the pointer */
+  /* then cast rights type to left */
+
+  /* first check the type for pointer assignement */
+  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);
+    }
+  else if (compareType (ltype, rtype) < 0)
+    right = geniCodeCast (ltype, right, TRUE);
+
+  /* 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 (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;
+
+      if (IS_TRUE_SYMOP (right))
+        sym = OP_SYMBOL (right);
+      ic = newiCode ('=', NULL, right);
+      IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
+      SPIL_LOC (right) = sym;
+      ADDTOCHAIN (ic);
+    }
+
+  ic = newiCode ('=', NULL, right);
+  IC_RESULT (ic) = left;
+  ADDTOCHAIN (ic);
+
+  /* if left isgptr flag is set then support
+     routine will be required */
+  if (left->isGptr)
+    ic->supportRtn = 1;
+
+  ic->nosupdate = nosupdate;
+  return left;
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeDummyRead - generate code for dummy read                */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeDummyRead (operand * op)
+{
+  iCode *ic;
+  sym_link *type = operandType (op);
+
+  if (!IS_VOLATILE(type))
+    return;
+
+  ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
+  ADDTOCHAIN (ic);
+
+  ic->nosupdate = 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSEParms - generate code for side effecting fcalls       */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSEParms - generate code for side effecting fcalls       */
 /*-----------------------------------------------------------------*/
-static void geniCodeSEParms (ast *parms)
+static void
+geniCodeSEParms (ast * parms,int lvl)
 {
 {
-    if (!parms)
-       return ;
+  if (!parms)
+    return;
 
 
-    if (parms->type == EX_OP && parms->opval.op == PARAM) {
-       geniCodeSEParms (parms->left) ;
-       geniCodeSEParms (parms->right);
-       return ;
+  if (parms->type == EX_OP && parms->opval.op == PARAM)
+    {
+      geniCodeSEParms (parms->left,lvl);
+      geniCodeSEParms (parms->right,lvl);
+      return;
     }
 
     }
 
-    /* hack don't like this but too lazy to think of
-       something better */
-    if (IS_ADDRESS_OF_OP(parms))
-       parms->left->lvalue = 1;
-    
-    if (IS_CAST_OP(parms) && 
-       IS_PTR(parms->ftype) && 
-       IS_ADDRESS_OF_OP(parms->right))
-       parms->right->left->lvalue = 1;
+  /* hack don't like this but too lazy to think of
+     something better */
+  if (IS_ADDRESS_OF_OP (parms))
+    parms->left->lvalue = 1;
 
 
-    parms->opval.oprnd = 
-       geniCodeRValue(ast2iCode (parms),FALSE);
-   
-    parms->type = EX_OPERAND ;
+  if (IS_CAST_OP (parms) &&
+      IS_PTR (parms->ftype) &&
+      IS_ADDRESS_OF_OP (parms->right))
+    parms->right->left->lvalue = 1;
+
+  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);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeParms - generates parameters                            */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeParms - generates parameters                            */
 /*-----------------------------------------------------------------*/
-static void geniCodeParms ( ast *parms , int *stack, link *fetype)
-{
-    iCode *ic ;
-    operand *pval ; 
-    
-    if ( ! parms )
-       return ;
-    
-    /* if this is a param node then do the left & right */
-    if (parms->type == EX_OP && parms->opval.op == PARAM) {
-       geniCodeParms (parms->left, stack,fetype) ;
-       geniCodeParms (parms->right, stack,fetype);
-       return ;
-    }
-    
-    /* get the parameter value */
-    if (parms->type == EX_OPERAND)
-       pval = parms->opval.oprnd ;
-    else {
-       /* maybe this else should go away ?? */
-       /* hack don't like this but too lazy to think of
-          something better */
-       if (IS_ADDRESS_OF_OP(parms))
-           parms->left->lvalue = 1;
-    
-       if (IS_CAST_OP(parms) && 
-           IS_PTR(parms->ftype) && 
-           IS_ADDRESS_OF_OP(parms->right))
-           parms->right->left->lvalue = 1;
-
-       pval = geniCodeRValue(ast2iCode (parms),FALSE); 
-    }
-
-    /* if register parm then make it a send */
-    if ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
-       IS_REGPARM(parms->etype)) {
-       ic = newiCode(SEND,pval,NULL);
-       ADDTOCHAIN(ic);
-    } else {
-       /* now decide whether to push or assign */
-       if (!(options.stackAuto || IS_RENT(fetype))) { 
-           
-           /* assign */
-           operand *top = operandFromSymbol(parms->argSym);
-           geniCodeAssign(top,pval,1);
-       }
-       else { 
-           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);
-       }
-    }
-    
+value *
+geniCodeParms (ast * parms, value *argVals, int *stack,
+               sym_link * ftype, int lvl)
+{
+  iCode *ic;
+  operand *pval;
+
+  if (!parms)
+    return argVals;
+
+  if (argVals==NULL) {
+    // first argument
+    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, ftype, lvl);
+      argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
+      return argVals;
+    }
+
+  /* get the parameter value */
+  if (parms->type == EX_OPERAND)
+    pval = parms->opval.oprnd;
+  else
+    {
+      /* maybe this else should go away ?? */
+      /* hack don't like this but too lazy to think of
+         something better */
+      if (IS_ADDRESS_OF_OP (parms))
+        parms->left->lvalue = 1;
+
+      if (IS_CAST_OP (parms) &&
+          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(ftype)) ||
+      IFFUNC_ISBUILTIN(ftype))
+    {
+      ic = newiCode (SEND, pval, NULL);
+      ic->argreg = SPEC_ARGREG(parms->etype);
+      ic->builtinSEND = FUNC_ISBUILTIN(ftype);
+      ADDTOCHAIN (ic);
+    }
+  else
+    {
+      /* now decide whether to push or assign */
+      if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
+        {
+
+          /* assign */
+          operand *top = operandFromSymbol (argVals->sym);
+          /* clear useDef and other bitVectors */
+          OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
+          geniCodeAssign (top, pval, 1, 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);
+        }
+    }
+
+  argVals=argVals->next;
+  return argVals;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeCall - generates temp code for calling                  */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeCall - generates temp code for calling                  */
 /*-----------------------------------------------------------------*/
-operand *geniCodeCall (operand *left, ast *parms)
-{ 
-    iCode *ic ;
-    operand *result ;
-    link *type, *etype;
-    int stack = 0 ;
-    
-    /* take care of parameters with side-effecting
-       function calls in them, this is required to take care 
-       of overlaying function parameters */
-    geniCodeSEParms ( parms );
-
-    /* first the parameters */
-    geniCodeParms ( parms , &stack , getSpec(operandType(left)));
-    
-    /* now call : if symbol then pcall */
-    if (IS_ITEMP(left)) 
-       ic = newiCode(PCALL,left,NULL);
-    else
-       ic = newiCode(CALL,left,NULL);
-    
-    IC_ARGS(ic) = left->operand.symOperand->args ;
-    type = copyLinkChain(operandType(left)->next);
-    etype = getSpec(type);
-    SPEC_EXTR(etype) = 0;
-    IC_RESULT(ic) = result = newiTempOperand(type,1);
-    
-    ADDTOCHAIN(ic);
-    
-    /* stack adjustment after call */
-    left->parmBytes = stack;
-
-    return result;
+operand *
+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_FUNCPTR(OP_SYMBOL(left)->type)) {
+    werror (E_FUNCTION_EXPECTED);
+    return operandFromValue(valueFromLit(0));
+  }
+
+  /* take care of parameters with side-effecting
+     function calls in them, this is required to take care
+     of overlaying function parameters */
+  geniCodeSEParms (parms,lvl);
+
+  ftype = operandType (left);
+  if (IS_FUNCPTR (ftype))
+    ftype = ftype->next;
+
+  /* first the parameters */
+  geniCodeParms (parms, NULL, &stack, ftype, lvl);
+
+  /* now call : if symbol then pcall */
+  if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
+    ic = newiCode (PCALL, left, NULL);
+  } else {
+    ic = newiCode (CALL, left, NULL);
+  }
+
+  type = copyLinkChain (ftype->next);
+  etype = getSpec (type);
+  SPEC_EXTR (etype) = 0;
+  IC_RESULT (ic) = result = newiTempOperand (type, 1);
+
+  ADDTOCHAIN (ic);
+
+  /* stack adjustment after call */
+  ic->parmBytes = stack;
+
+  return result;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeReceive - generate intermediate code for "receive"      */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeReceive - generate intermediate code for "receive"      */
 /*-----------------------------------------------------------------*/
-static void geniCodeReceive (value *args)
-{   
-    /* for all arguments that are passed in registers */
-    while (args) {
-
-       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) {
-               } 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);
-           currFunc->recvSize = getSize(sym->etype);
-           IC_RESULT(ic) = opr;
-           ADDTOCHAIN(ic);
-       }
-       
-       args = args->next;
+static void
+geniCodeReceive (value * args, operand * func)
+{
+  unsigned char paramByteCounter = 0;
+
+  /* for all arguments that are passed in registers */
+  while (args)
+    {
+      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)) && !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;
     }
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeFunctionBody - create the function body                 */
 /*-----------------------------------------------------------------*/
     }
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeFunctionBody - create the function body                 */
 /*-----------------------------------------------------------------*/
-void geniCodeFunctionBody (ast *tree)
-{
-    iCode *ic ;
-    operand *func ;
-    link *fetype  ;
-    int savelineno ;
-    
-    /* reset the auto generation */
-    /* numbers */
-    iTempNum = 0 ;
-    iTempLblNum = 0;   
-    operandKey = 0 ;
-    iCodeKey = 0 ;
-    func  = ast2iCode(tree->left);
-    fetype = getSpec(operandType(func));
-    
-    savelineno = lineno;
-    lineno = OP_SYMBOL(func)->lineDef;
-    /* create an entry label */
-    geniCodeLabel(entryLabel);    
-    lineno = savelineno;
-
-    /* create a proc icode */
-    ic = newiCode(FUNCTION,func,NULL);
-    /* if the function has parmas   then */
-    /* save the parameters information    */
-    ic->argLabel.args = tree->values.args ;
-    ic->lineno = OP_SYMBOL(func)->lineDef;
-
-    ADDTOCHAIN(ic);   
-    
-    /* for all parameters that are passed
-       on registers add a "receive" */
-    geniCodeReceive( tree->values.args );
-
-    /* generate code for the body */
-    ast2iCode(tree->right);
-    
-    /* create a label for return */
-    geniCodeLabel(returnLabel);
-    
-    /* now generate the end proc */
-    ic = newiCode(ENDFUNCTION,func,NULL);
-    ADDTOCHAIN(ic);
-    return ;
+void
+geniCodeFunctionBody (ast * tree,int lvl)
+{
+  iCode *ic;
+  operand *func;
+  sym_link *fetype;
+  int savelineno;
+
+  /* reset the auto generation */
+  /* numbers */
+  iTempNum = 0;
+  iTempLblNum = 0;
+  operandKey = 0;
+  iCodeKey = 0;
+  func = ast2iCode (tree->left,lvl+1);
+  fetype = getSpec (operandType (func));
+
+  savelineno = lineno;
+  lineno = OP_SYMBOL (func)->lineDef;
+  /* create an entry label */
+  geniCodeLabel (entryLabel);
+  lineno = savelineno;
+
+  /* create a proc icode */
+  ic = newiCode (FUNCTION, func, NULL);
+  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, func);
+
+  /* generate code for the body */
+  ast2iCode (tree->right,lvl+1);
+
+  /* create a label for return */
+  geniCodeLabel (returnLabel);
+
+  /* now generate the end proc */
+  ic = newiCode (ENDFUNCTION, func, NULL);
+  ic->tree = tree;
+  ADDTOCHAIN (ic);
+  return;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeReturn - gen icode for 'return' statement               */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeReturn - gen icode for 'return' statement               */
 /*-----------------------------------------------------------------*/
-void geniCodeReturn (operand *op)
+void
+geniCodeReturn (operand * op)
 {
 {
-    iCode *ic;
-    
-    /* if the operand is present force an rvalue */
-    if (op) 
-       op = geniCodeRValue(op,FALSE);    
-    
-    ic = newiCode(RETURN,op,NULL);
-    ADDTOCHAIN(ic);
+  iCode *ic;
+
+  /* if the operand is present force an rvalue */
+  if (op)
+    op = geniCodeRValue (op, FALSE);
+
+  ic = newiCode (RETURN, op, NULL);
+  ADDTOCHAIN (ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeIfx - generates code for extended if statement          */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeIfx - generates code for extended if statement          */
 /*-----------------------------------------------------------------*/
-void geniCodeIfx (ast *tree)
-{
-    iCode *ic;
-    operand *condition = ast2iCode(tree->left);
-    link *cetype; 
-    
-    /* if condition is null then exit */
-    if (!condition)
-       goto exit ;
-    else
-       condition = geniCodeRValue(condition,FALSE);
-    
-    cetype = getSpec(operandType(condition));
-    /* if the condition is a literal */
-    if (IS_LITERAL(cetype)) {
-       if (floatFromVal(condition->operand.valOperand)) {
-           if (tree->trueLabel)
-               geniCodeGoto(tree->trueLabel);
-           else
-               assert(1);
-       }
-       else {
-           if (tree->falseLabel)
-               geniCodeGoto (tree->falseLabel);
-           else
-               assert(1);
-       }
-       goto exit;
-    }
-    
-    if ( tree->trueLabel ) {
-       ic = newiCodeCondition(condition,
-                              tree->trueLabel,
-                              NULL );
-       ADDTOCHAIN(ic);
-       
-       if ( tree->falseLabel) 
-           geniCodeGoto(tree->falseLabel);     
-    }
-    else {
-       ic = newiCodeCondition (condition,
-                               NULL,
-                               tree->falseLabel);
-       ADDTOCHAIN(ic);
-    }
-    
- exit:
-    ast2iCode(tree->right);
+void
+geniCodeIfx (ast * tree,int lvl)
+{
+  iCode *ic;
+  operand *condition = ast2iCode (tree->left,lvl+1);
+  sym_link *cetype;
+
+  /* if condition is null then exit */
+  if (!condition)
+    goto exit;
+  else
+    condition = geniCodeRValue (condition, FALSE);
+
+  cetype = getSpec (operandType (condition));
+  /* if the condition is a literal */
+  if (IS_LITERAL (cetype))
+    {
+      if (floatFromVal (condition->operand.valOperand))
+        {
+          if (tree->trueLabel)
+            geniCodeGoto (tree->trueLabel);
+          else
+            assert (0);
+        }
+      else
+        {
+          if (tree->falseLabel)
+            geniCodeGoto (tree->falseLabel);
+          else
+            assert (0);
+        }
+      goto exit;
+    }
+
+  if (tree->trueLabel)
+    {
+      ic = newiCodeCondition (condition,
+                              tree->trueLabel,
+                              NULL);
+      ADDTOCHAIN (ic);
+
+      if (tree->falseLabel)
+        geniCodeGoto (tree->falseLabel);
+    }
+  else
+    {
+      ic = newiCodeCondition (condition,
+                              NULL,
+                              tree->falseLabel);
+      ADDTOCHAIN (ic);
+    }
+
+exit:
+  ast2iCode (tree->right,lvl+1);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeJumpTable - tries to create a jump table for switch     */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeJumpTable - tries to create a jump table for switch     */
 /*-----------------------------------------------------------------*/
-int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
-{
-    int min = 0 ,max = 0, t, cnt = 0;
-    value *vch;
-    iCode *ic;
-    operand *boundary;
-    symbol *falseLabel;
-    set *labels = NULL ;
-
-    if (!tree || !caseVals)
-       return 0;
-
-    /* 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);
-    sprintf(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;
-
-    while (vch) {
-       if (((t = (int)floatFromVal(vch)) - max) != 1)
-           return 0;
-       sprintf(buffer,"_case_%d_%d",
-               tree->values.switchVals.swNum,
-               t);
-       addSet(&labels,newiTempLabel(buffer));
-       max = t;
-       cnt++ ;
-       vch = vch->next ;
-    }
-    
-    /* 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))
-       return 0;
-    
-    if ( tree->values.switchVals.swDefault )
-       sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
-    else
-       sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
-    
-    falseLabel = newiTempLabel (buffer);
-
-    /* so we can create a jumptable */
-    /* first we rule out the boundary conditions */
-    /* if only optimization says so */
-    if ( ! optimize.noJTabBoundary ) {
-       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);
-       }
-
-       /* now for upper bounds */
-       boundary = geniCodeLogic(cond,operandFromLit(max),'>');
-       ic = newiCodeCondition (boundary,falseLabel,NULL);
-       ADDTOCHAIN(ic);
-    }
-
-    /* if the min is not zero then we no make it zero */
-    if (min) {
-       cond = geniCodeSubtract(cond,operandFromLit(min));
-       setOperandType(cond, UCHARTYPE);
-    }
-
-    /* now create the jumptable */
-    ic = newiCode(JUMPTABLE,NULL,NULL);
-    IC_JTCOND(ic) = cond;
-    IC_JTLABELS(ic) = labels;
-    ADDTOCHAIN(ic);
-    return 1;       
+int
+geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
+{
+  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;
+
+  /* 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 */
+  /* If not all integer numbers are present the algorithm */
+  /* inserts jumps to the default label for the missing numbers */
+  /* and decides later whether it is worth it */
+  min = (int) floatFromVal (vch = caseVals);
+
+  while (vch->next)
+    {
+      cnt++;
+      vch = vch->next;
+    }
+  max = (int) floatFromVal (vch);
+
+  /* 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);
+    }
+  else
+    {
+      SNPRINTF (buffer, sizeof(buffer),
+                "_swBrk_%d",
+                tree->values.switchVals.swNum);
+    }
+  falseLabel = newiTempLabel (buffer);
+
+  /* Build the list of labels for the jump table. */
+  vch = caseVals;
+  t = (int) floatFromVal (vch);
+  for (i=min; i<=max; i++)
+    {
+      if (vch && t==i)
+        {
+          /* Explicit case: make a new label for it. */
+          SNPRINTF (buffer, sizeof(buffer),
+                    "_case_%d_%d",
+                    tree->values.switchVals.swNum,
+                    i);
+          addSet (&labels, newiTempLabel (buffer));
+          vch = vch->next;
+          if (vch)
+            t = (int) floatFromVal (vch);
+        }
+      else
+        {
+          /* Implicit case: use the default label. */
+          addSet (&labels, falseLabel);
+        }
+    }
+
+  /* first we rule out the boundary conditions */
+  /* if only optimization says so */
+  if (needRangeCheck)
+    {
+      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 && IS_UNSIGNED (cetype)))
+        {
+          boundary = geniCodeLogic (cond, operandFromLit (min), '<');
+          ic = newiCodeCondition (boundary, falseLabel, NULL);
+          ADDTOCHAIN (ic);
+        }
+
+      /* now for upper bounds */
+      boundary = geniCodeLogic (cond, operandFromLit (max), '>');
+      ic = newiCodeCondition (boundary, falseLabel, NULL);
+      ADDTOCHAIN (ic);
+    }
+
+  /* if the min is not zero then we no make it zero */
+  if (min)
+    {
+      cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
+      if (!IS_LITERAL(getSpec(operandType(cond))))
+        setOperandType (cond, UCHARTYPE);
+    }
+
+  /* now create the jumptable */
+  ic = newiCode (JUMPTABLE, NULL, NULL);
+  IC_JTCOND (ic) = cond;
+  IC_JTLABELS (ic) = labels;
+  ADDTOCHAIN (ic);
+  return 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSwitch - changes a switch to a if statement             */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeSwitch - changes a switch to a if statement             */
 /*-----------------------------------------------------------------*/
-void geniCodeSwitch (ast *tree)
-{
-    iCode *ic ;
-    operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
-    value *caseVals = tree->values.switchVals.swVals ;
-    symbol *trueLabel , *falseLabel;
-    
-    /* if we can make this a jump table */
-    if ( geniCodeJumpTable (cond,caseVals,tree) )
-       goto jumpTable ; /* no need for the comparison */
-
-    /* for the cases defined do */
-    while (caseVals) {
-       
-       operand *compare = geniCodeLogic (cond,
-                                         operandFromValue(caseVals),
-                                         EQ_OP);
-       
-       sprintf(buffer,"_case_%d_%d",
-               tree->values.switchVals.swNum,
-               (int) floatFromVal(caseVals));
-       trueLabel = newiTempLabel(buffer);
-       
-       ic = newiCodeCondition(compare,trueLabel,NULL);
-       ADDTOCHAIN(ic);
-       caseVals = caseVals->next;
-    }
-
-
-    
-    /* if default is present then goto break else break */
-    if ( tree->values.switchVals.swDefault )
-       sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
-    else
-       sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
-    
-    falseLabel = newiTempLabel (buffer);
-    geniCodeGoto(falseLabel);
- jumpTable:   
-    ast2iCode(tree->right);
-} 
+void
+geniCodeSwitch (ast * tree,int lvl)
+{
+  iCode *ic;
+  operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
+  value *caseVals = tree->values.switchVals.swVals;
+  symbol *trueLabel, *falseLabel;
+
+  /* If the condition is a literal, then just jump to the */
+  /* appropriate case label. */
+  if (IS_LITERAL(getSpec(operandType(cond))))
+    {
+      int switchVal, caseVal;
+
+      switchVal = (int) floatFromVal (cond->operand.valOperand);
+      while (caseVals)
+        {
+          caseVal = (int) floatFromVal (caseVals);
+          if (caseVal == switchVal)
+            {
+              SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
+                        tree->values.switchVals.swNum, caseVal);
+              trueLabel = newiTempLabel (buffer);
+              geniCodeGoto (trueLabel);
+              goto jumpTable;
+            }
+          caseVals = caseVals->next;
+        }
+      goto defaultOrBreak;
+    }
+
+  /* If 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 */
+
+  /* for the cases defined do */
+  while (caseVals)
+    {
+
+      operand *compare = geniCodeLogic (cond,
+                                        operandFromValue (caseVals),
+                                        EQ_OP);
+
+      SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
+               tree->values.switchVals.swNum,
+               (int) floatFromVal (caseVals));
+      trueLabel = newiTempLabel (buffer);
+
+      ic = newiCodeCondition (compare, trueLabel, NULL);
+      ADDTOCHAIN (ic);
+      caseVals = caseVals->next;
+    }
+
+
+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);
+    }
+  else
+    {
+        SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+    }
+
+  falseLabel = newiTempLabel (buffer);
+  geniCodeGoto (falseLabel);
+
+jumpTable:
+  ast2iCode (tree->right,lvl+1);
+}
 
 /*-----------------------------------------------------------------*/
 /* geniCodeInline - intermediate code for inline assembler         */
 /*-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------*/
 /* geniCodeInline - intermediate code for inline assembler         */
 /*-----------------------------------------------------------------*/
-static void geniCodeInline (ast *tree)
+static void
+geniCodeInline (ast * tree)
 {
 {
-    iCode *ic;
+  iCode *ic;
+
+  ic = newiCode (INLINEASM, NULL, NULL);
+  IC_INLINE (ic) = tree->values.inlineasm;
+  ADDTOCHAIN (ic);
+}
 
 
-    ic = newiCode(INLINEASM,NULL,NULL);
-    IC_INLINE(ic) = tree->values.inlineasm;
-    ADDTOCHAIN(ic);
+/*-----------------------------------------------------------------*/
+/* geniCodeArrayInit - intermediate code for array initializer     */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeArrayInit (ast * tree, operand *array)
+{
+  iCode *ic;
+
+  if (!getenv("TRY_THE_NEW_INITIALIZER")) {
+    ic = newiCode (ARRAYINIT, array, NULL);
+    IC_ARRAYILIST (ic) = tree->values.constlist;
+  } else {
+    operand *left=newOperand(), *right=newOperand();
+    left->type=right->type=SYMBOL;
+    OP_SYMBOL(left)=AST_SYMBOL(tree->left);
+    OP_SYMBOL(right)=AST_SYMBOL(tree->right);
+    ic = newiCode (ARRAYINIT, left, right);
+  }
+  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)
+    {
+      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   */
+/*-----------------------------------------------------------------*/
+set * lvaluereqSet = NULL;
+typedef struct lvalItem
+  {
+    int req;
+    int lvl;
+  }
+lvalItem;
+
+/*-----------------------------------------------------------------*/
+/* addLvaluereq - add a flag for lvalreq for current ast level     */
+/*-----------------------------------------------------------------*/
+void addLvaluereq(int lvl)
+{
+  lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
+  lpItem->req=1;
+  lpItem->lvl=lvl;
+  addSetHead(&lvaluereqSet,lpItem);
+
+}
+/*-----------------------------------------------------------------*/
+/* delLvaluereq - del a flag for lvalreq for current ast level     */
+/*-----------------------------------------------------------------*/
+void delLvaluereq()
+{
+  lvalItem * lpItem;
+  lpItem = getSet(&lvaluereqSet);
+  if(lpItem) Safe_free(lpItem);
+}
+/*-----------------------------------------------------------------*/
+/* clearLvaluereq - clear lvalreq flag                             */
+/*-----------------------------------------------------------------*/
+void clearLvaluereq()
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) lpItem->req = 0;
+}
+/*-----------------------------------------------------------------*/
+/* getLvaluereq - get the last lvalreq level                       */
+/*-----------------------------------------------------------------*/
+int getLvaluereqLvl()
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) return lpItem->lvl;
+  return 0;
+}
+/*-----------------------------------------------------------------*/
+/* isLvaluereq - is lvalreq valid for this level ?                 */
+/*-----------------------------------------------------------------*/
+int isLvaluereq(int lvl)
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* ast2iCode - creates an icodeList from an ast                    */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* ast2iCode - creates an icodeList from an ast                    */
 /*-----------------------------------------------------------------*/
-operand *ast2iCode (ast *tree)
-{
-    operand *left = NULL;
-    operand *right= NULL;
-    
-    if (!tree)
-       return NULL ;
-    
-    /* set the global variables for filename & line number */
-    if ( tree->filename )
-       filename =  tree->filename ;
-    if ( tree->lineno)
-       lineno   = tree->lineno ;
-    if (tree->block)
-       block = tree->block ;
-    if (tree->level)
-       scopeLevel = tree->level;
-    
-    if (tree->type == EX_VALUE )
-       return operandFromValue(tree->opval.val);
-    
-    if (tree->type == EX_LINK )
-       return operandFromLink (tree->opval.lnk);
-    
-    /* if we find a nullop */
-    if (tree->type == EX_OP && 
-       ( tree->opval.op == NULLOP || 
-         tree->opval.op == BLOCK )) {
-       ast2iCode (tree->left);
-       ast2iCode (tree->right);
-       return NULL ;
-    }
-    
-    /* special cases for not evaluating */
-    if ( tree->opval.op != ':'   && 
-        tree->opval.op != '?'   &&
-        tree->opval.op != CALL  && 
-        tree->opval.op != IFX   &&
-        tree->opval.op != LABEL &&
-        tree->opval.op != GOTO  &&     
-        tree->opval.op != SWITCH &&
-        tree->opval.op != FUNCTION &&
-        tree->opval.op != INLINEASM ) {
-       if (IS_ASSIGN_OP(tree->opval.op) || 
-           IS_DEREF_OP(tree)            || 
-           (tree->opval.op == '&' && !tree->right) ||
-           tree->opval.op == PTR_OP) {
-           lvaluereq++;
-           left = operandFromAst(tree->left);
-           lvaluereq--;
-       } else {
-           left =  operandFromAst(tree->left);
-       }
-       if (tree->opval.op == INC_OP || 
-           tree->opval.op == DEC_OP) {
-           lvaluereq++;
-           right= operandFromAst(tree->right);
-           lvaluereq--;
-       } else {
-           right= operandFromAst(tree->right);
-       }
-    }
-    
-    /* now depending on the type of operand */
-    /* this will be a biggy                 */
-    switch (tree->opval.op) {
-       
-    case '[' :    /* array operation */
-       {
-           link *ltype = operandType(left);
-           left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
-           right=geniCodeRValue (right,TRUE);             
-       }
-       
-       return geniCodeArray (left,right);
-       
-    case '.' :   /* structure dereference */
-       if (IS_PTR(operandType(left)))
-           left = geniCodeRValue(left,TRUE);
-       else
-           left = geniCodeRValue(left,FALSE);            
-       
-       return geniCodeStruct (left,right,tree->lvalue);
-       
-    case PTR_OP: /* structure pointer dereference */
-       {
-           link *pType;
-           pType = operandType(left);
-           left = geniCodeRValue(left,TRUE);
-           
-           setOClass (pType,getSpec(operandType(left)));
-       }              
-       
-       return geniCodeStruct (left, right,tree->lvalue);
-       
-    case INC_OP: /* increment operator */
-       if ( left )
-           return geniCodePostInc (left);
-       else
-           return geniCodePreInc (right);
-       
-    case DEC_OP: /* decrement operator */
-       if ( left )
-           return geniCodePostDec (left);
-       else
-           return geniCodePreDec (right);
-       
-    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);
-       } else
-           return geniCodeAddressOf (left);
-       
-    case '|': /* bitwise or & xor */
+operand *
+ast2iCode (ast * tree,int lvl)
+{
+  operand *left = NULL;
+  operand *right = NULL;
+  if (!tree)
+    return NULL;
+
+  /* set the global variables for filename & line number */
+  if (tree->filename)
+    filename = tree->filename;
+  if (tree->lineno)
+    lineno = tree->lineno;
+  if (tree->block)
+    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);
+
+  if (tree->type == EX_LINK)
+    return operandFromLink (tree->opval.lnk);
+
+  /* if we find a nullop */
+  if (tree->type == EX_OP &&
+     (tree->opval.op == NULLOP ||
+     tree->opval.op == BLOCK))
+    {
+      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;
+    }
+
+  /* special cases for not evaluating */
+  if (tree->opval.op != ':' &&
+      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 != CRITICAL)
+    {
+
+        if (IS_ASSIGN_OP (tree->opval.op) ||
+           IS_DEREF_OP (tree) ||
+           (tree->opval.op == '&' && !tree->right) ||
+           tree->opval.op == PTR_OP)
+          {
+            addLvaluereq(lvl);
+            if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
+               (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
+              clearLvaluereq();
+
+            left = operandFromAst (tree->left,lvl);
+            delLvaluereq();
+            if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
+              left = geniCodeRValue (left, TRUE);
+          }
+        else
+          {
+            left = operandFromAst (tree->left,lvl);
+          }
+        if (tree->opval.op == INC_OP ||
+            tree->opval.op == DEC_OP)
+          {
+            addLvaluereq(lvl);
+            right = operandFromAst (tree->right,lvl);
+            delLvaluereq();
+          }
+        else
+          {
+            right = operandFromAst (tree->right,lvl);
+          }
+      }
+
+  /* now depending on the type of operand */
+  /* this will be a biggy                 */
+  switch (tree->opval.op)
+    {
+
+    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);
+      }
+
+      return geniCodeArray (left, right,lvl);
+
+    case '.':                   /* structure dereference */
+      if (IS_PTR (operandType (left)))
+        left = geniCodeRValue (left, TRUE);
+      else
+        left = geniCodeRValue (left, FALSE);
+
+      return geniCodeStruct (left, right, tree->lvalue);
+
+    case PTR_OP:                /* structure pointer dereference */
+      {
+        sym_link *pType;
+        pType = operandType (left);
+        left = geniCodeRValue (left, TRUE);
+
+        setOClass (pType, getSpec (operandType (left)));
+      }
+
+      return geniCodeStruct (left, right, tree->lvalue);
+
+    case INC_OP:                /* increment operator */
+      if (left)
+        return geniCodePostInc (left);
+      else
+        return geniCodePreInc (right, tree->lvalue);
+
+    case DEC_OP:                /* decrement operator */
+      if (left)
+        return geniCodePostDec (left);
+      else
+        return geniCodePreDec (right, tree->lvalue);
+
+    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);
+        }
+      else
+        return geniCodeAddressOf (left);
+
+    case '|':                   /* bitwise or & xor */
     case '^':
     case '^':
-       return geniCodeBitwise (geniCodeRValue(left,FALSE),
-                               geniCodeRValue(right,FALSE),
-                               tree->opval.op,
-                               tree->ftype);
-       
+      return geniCodeBitwise (geniCodeRValue (left, FALSE),
+                              geniCodeRValue (right, FALSE),
+                              tree->opval.op,
+                              tree->ftype);
+
     case '/':
     case '/':
-       return geniCodeDivision (geniCodeRValue(left,FALSE),
-                                geniCodeRValue(right,FALSE));
-       
-    case '%' :
-       return geniCodeModulus (geniCodeRValue(left,FALSE),
-                               geniCodeRValue(right,FALSE));
+      return geniCodeDivision (geniCodeRValue (left, FALSE),
+                               geniCodeRValue (right, FALSE),
+                               getResultTypeFromType (tree->ftype));
+
+    case '%':
+      return geniCodeModulus (geniCodeRValue (left, FALSE),
+                              geniCodeRValue (right, FALSE),
+                              getResultTypeFromType (tree->ftype));
     case '*':
     case '*':
-       if ( right ) 
-           return geniCodeMultiply (geniCodeRValue(left,FALSE),
-                                    geniCodeRValue(right,FALSE));
-       else        
-           return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
-       
-    case '-' :
-       if ( right ) 
-           return geniCodeSubtract (geniCodeRValue(left,FALSE),
-                                    geniCodeRValue(right,FALSE));
-       else
-           return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
-       
-    case '+' :
-       if ( right ) 
-           return geniCodeAdd (geniCodeRValue(left,FALSE),
-                               geniCodeRValue(right,FALSE));
-       else
-           return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
-       
+      if (right)
+        return geniCodeMultiply (geniCodeRValue (left, FALSE),
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype));
+      else
+        return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
+
+    case '-':
+      if (right)
+        return geniCodeSubtract (geniCodeRValue (left, FALSE),
+                                 geniCodeRValue (right, FALSE),
+                                 getResultTypeFromType (tree->ftype));
+      else
+        return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
+
+    case '+':
+      if (right)
+        return geniCodeAdd (geniCodeRValue (left, FALSE),
+                            geniCodeRValue (right, FALSE),
+                            getResultTypeFromType (tree->ftype),
+                            lvl);
+      else
+        return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
+
     case LEFT_OP:
     case LEFT_OP:
-       return geniCodeLeftShift (geniCodeRValue(left,FALSE),
-                                 geniCodeRValue(right,FALSE));
-       
+      return geniCodeLeftShift (geniCodeRValue (left, FALSE),
+                                geniCodeRValue (right, FALSE),
+                                getResultTypeFromType (tree->ftype));
+
     case RIGHT_OP:
     case RIGHT_OP:
-       return geniCodeRightShift (geniCodeRValue(left,FALSE),
-                                  geniCodeRValue(right,FALSE));
+      return geniCodeRightShift (geniCodeRValue (left, FALSE),
+                                 geniCodeRValue (right, FALSE));
     case CAST:
     case CAST:
-       return geniCodeCast (operandType(left),
-                            geniCodeRValue(right,FALSE),FALSE);
-       
-    case '~' :
-    case '!' :
+#if 0 // this indeed needs a second thought
+      {
+        operand *op;
+
+        // let's keep this simple: get the rvalue we need
+        op=geniCodeRValue (right, FALSE);
+        // now cast it to whatever we want
+        op=geniCodeCast (operandType(left), op, FALSE);
+        // if this is going to be used as an lvalue, make it so
+        if (tree->lvalue) {
+          op->isaddr=1;
+        }
+        return op;
+      }
+#else // bug #604575, is it a bug ????
+      return geniCodeCast (operandType (left),
+                           geniCodeRValue (right, FALSE), FALSE);
+#endif
+
+    case '~':
+      {
+        sym_link *ltype = operandType (left);
+        operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
+        if ((SPEC_NOUN(ltype) == V_CHAR) && IS_UNSIGNED(ltype))
+          {
+            setOperandType (op, INTTYPE);
+          }
+        return op;
+      }
     case RRC:
     case RRC:
-    case RLC:  
-       return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
-       
+    case RLC:
+    case SWAP:
+      return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
+
+    case '!':
     case GETHBIT:
     case GETHBIT:
-       {
-           operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
-           setOperandType(op, UCHARTYPE);
-           return op;
-       }
-    case '>' :
-    case '<' :
+      {
+        operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
+        setOperandType (op, UCHARTYPE);
+        return op;
+      }
+    case AND_OP:
+    case OR_OP:
+      return geniCodeLogicAndOr (tree, lvl);
+    case '>':
+    case '<':
     case LE_OP:
     case GE_OP:
     case EQ_OP:
     case NE_OP:
     case LE_OP:
     case GE_OP:
     case EQ_OP:
     case NE_OP:
-    case AND_OP:
-    case OR_OP:
-       return geniCodeLogic (geniCodeRValue(left,FALSE),
-                             geniCodeRValue(right,FALSE),
-                             tree->opval.op);
-    case '?' : 
-       return geniCodeConditional (tree); 
-       
+      /* different compilers (even different gccs) evaluate
+         the two calls in a different order. to get the same
+         result on all machines we've to specify a clear sequence.
+      return geniCodeLogic (geniCodeRValue (left, FALSE),
+                            geniCodeRValue (right, FALSE),
+                            tree->opval.op);
+      */
+      {
+        operand *leftOp, *rightOp;
+
+        leftOp  = geniCodeRValue (left , FALSE);
+        rightOp = geniCodeRValue (right, FALSE);
+
+        return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+      }
+    case '?':
+      return geniCodeConditional (tree,lvl);
+
     case SIZEOF:
     case SIZEOF:
-       return operandFromLit(getSize(tree->right->ftype));
-       
-    case '='        :
-       {
-           link *rtype = operandType(right);
-           link *ltype = operandType(left);
-           if (IS_PTR(rtype) && IS_ITEMP(right) 
-               && right->isaddr && checkType(rtype->next,ltype)==1)
-               right =  geniCodeRValue(right,TRUE);
-           else
-               right = geniCodeRValue(right,FALSE);
-
-           geniCodeAssign (left,right,0);
-           return right ;
-       }              
+      return operandFromLit (getSize (tree->right->ftype));
+
+    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, 1);
+        return right;
+      }
     case MUL_ASSIGN:
     case MUL_ASSIGN:
-       return 
-           geniCodeAssign(left,
-                          geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
-                                                           FALSE),
-                                           geniCodeRValue(right,FALSE)),0);
-                                               
+      return
+        geniCodeAssign (left,
+                geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  getResultTypeFromType (tree->ftype)),
+                        0, 1);
+
     case DIV_ASSIGN:
     case DIV_ASSIGN:
-       return 
-           geniCodeAssign(left,
-                          geniCodeDivision(geniCodeRValue(operandFromOperand(left),
-                                                          FALSE),
-                                           geniCodeRValue(right,FALSE)),0);
+      return
+        geniCodeAssign (left,
+                geniCodeDivision (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  getResultTypeFromType (tree->ftype)),
+                        0, 1);
     case MOD_ASSIGN:
     case MOD_ASSIGN:
-       return 
-           geniCodeAssign(left,
-                          geniCodeModulus(geniCodeRValue(operandFromOperand(left),
-                                                         FALSE),
-                                          geniCodeRValue(right,FALSE)),0);
-    case ADD_ASSIGN: 
-       {
-           link *rtype = operandType(right);
-           link *ltype = operandType(left);
-           if (IS_PTR(rtype) && IS_ITEMP(right) 
-               && right->isaddr && checkType(rtype->next,ltype)==1)
-               right =  geniCodeRValue(right,TRUE);
-           else
-               right = geniCodeRValue(right,FALSE);
-
-          
-           return geniCodeAssign(left,
-                                 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
-                                                             FALSE),
-                                              right),0);
-       }
+      return
+        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,
+                                  getResultTypeFromType (tree->ftype),
+                                  lvl),
+                               0, 1);
+      }
     case SUB_ASSIGN:
     case SUB_ASSIGN:
-       {
-           link *rtype = operandType(right);
-           link *ltype = operandType(left);
-           if (IS_PTR(rtype) && IS_ITEMP(right) 
-               && right->isaddr && checkType(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:
     case LEFT_ASSIGN:
-       return 
-           geniCodeAssign (left,
-                           geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
-                                                            ,FALSE),
-                                             geniCodeRValue(right,FALSE)),0);
+      return
+        geniCodeAssign (left,
+                geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
+                                                   ,FALSE),
+                                   geniCodeRValue (right, FALSE),
+                                   getResultTypeFromType (tree->ftype)),
+                        0, 1);
     case RIGHT_ASSIGN:
     case RIGHT_ASSIGN:
-       return 
-           geniCodeAssign(left,
-                          geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
-                                                            ,FALSE),
-                                             geniCodeRValue(right,FALSE)),0);
+      return
+        geniCodeAssign (left,
+               geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
+                                                   ,FALSE),
+                                   geniCodeRValue (right, FALSE)), 0, 1);
     case AND_ASSIGN:
     case AND_ASSIGN:
-       return 
-           geniCodeAssign (left,
-                           geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
-                                                          FALSE),
-                                           geniCodeRValue(right,FALSE),
-                                           BITWISEAND,
-                                           operandType(left)),0);
+      return
+        geniCodeAssign (left,
+                 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  BITWISEAND,
+                                  operandType (left)), 0, 1);
     case XOR_ASSIGN:
     case XOR_ASSIGN:
-       return 
-           geniCodeAssign (left,
-                           geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
-                                                           FALSE),
-                                            geniCodeRValue(right,FALSE),
-                                            '^',
-                                            operandType(left)),0);
+      return
+        geniCodeAssign (left,
+                 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
+                                                  FALSE),
+                                  geniCodeRValue (right, FALSE),
+                                  '^',
+                                  operandType (left)), 0, 1);
     case OR_ASSIGN:
     case OR_ASSIGN:
-       return 
-           geniCodeAssign (left,
-                           geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
-                                                           ,FALSE),
-                                            geniCodeRValue(right,FALSE),
-                                            '|',
-                                            operandType(left)),0);
-    case ',' :
-       return geniCodeRValue(right,FALSE);
-       
+      return
+        geniCodeAssign (left,
+                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
+                                                   ,FALSE),
+                                   geniCodeRValue (right, FALSE),
+                                   '|',
+                                   operandType (left)), 0, 1);
+    case ',':
+      return geniCodeRValue (right, FALSE);
+
     case CALL:
     case CALL:
-       return geniCodeCall (ast2iCode(tree->left),
-                            tree->right);
+      return geniCodeCall (ast2iCode (tree->left,lvl+1),
+                           tree->right,lvl);
     case LABEL:
     case LABEL:
-       geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
-       return ast2iCode (tree->right);
-       
+      geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+      return ast2iCode (tree->right,lvl+1);
+
     case GOTO:
     case GOTO:
-       geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
-       return ast2iCode (tree->right);
-       
+      geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+      return ast2iCode (tree->right,lvl+1);
+
     case FUNCTION:
     case FUNCTION:
-       geniCodeFunctionBody ( tree );
-       return NULL ;
-       
+      geniCodeFunctionBody (tree,lvl);
+      return NULL;
+
     case RETURN:
     case RETURN:
-       geniCodeReturn (right);
-       return NULL ;
-       
+      geniCodeReturn (right);
+      return NULL;
+
     case IFX:
     case IFX:
-       geniCodeIfx (tree);
-       return NULL ;
-       
+      geniCodeIfx (tree,lvl);
+      return NULL;
+
     case SWITCH:
     case SWITCH:
-       geniCodeSwitch (tree);
-       return NULL;
+      geniCodeSwitch (tree,lvl);
+      return NULL;
 
     case INLINEASM:
 
     case INLINEASM:
-       geniCodeInline (tree);
-       return NULL ;
+      geniCodeInline (tree);
+      return NULL;
+
+    case ARRAYINIT:
+        geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
+        return NULL;
+
+    case CRITICAL:
+        geniCodeCritical (tree, lvl);
     }
     }
-    
-    return NULL;
+
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
 /* reverseICChain - gets from the list and creates a linkedlist    */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* reverseICChain - gets from the list and creates a linkedlist    */
 /*-----------------------------------------------------------------*/
-iCode *reverseiCChain ()
+iCode *
+reverseiCChain ()
 {
 {
-    iCode *loop = NULL ;
-    iCode *prev = NULL ;
-    
-    while ((loop = getSet(&iCodeChain))) {
-       loop->next = prev ;
-       if ( prev )
-           prev->prev = loop; 
-       prev = loop ;
+  iCode *loop = NULL;
+  iCode *prev = NULL;
+
+  while ((loop = getSet (&iCodeChain)))
+    {
+      loop->next = prev;
+      if (prev)
+        prev->prev = loop;
+      prev = loop;
     }
     }
-    
-    return prev;
+
+  return prev;
 }
 
 
 /*-----------------------------------------------------------------*/
 /* iCodeFromAst - given an ast will convert it to iCode            */
 /*-----------------------------------------------------------------*/
 }
 
 
 /*-----------------------------------------------------------------*/
 /* iCodeFromAst - given an ast will convert it to iCode            */
 /*-----------------------------------------------------------------*/
-iCode *iCodeFromAst ( ast *tree )
+iCode *
+iCodeFromAst (ast * tree)
+{
+  returnLabel = newiTempLabel ("_return");
+  entryLabel = newiTempLabel ("_entry");
+  ast2iCode (tree,0);
+  return reverseiCChain ();
+}
+
+static const char *opTypeToStr(OPTYPE op)
 {
 {
-    returnLabel = newiTempLabel("_return");
-    entryLabel  = newiTempLabel("_entry") ;
-    ast2iCode (tree);
-    return reverseiCChain ();
+    switch(op)
+    {
+      case SYMBOL: return "symbol";
+      case VALUE: return "value";
+      case TYPE: return "type";
+    }
+    return "undefined type";
 }
 
 }
 
+
+operand *validateOpType(operand         *op,
+                        const char      *macro,
+                        const char      *args,
+                        OPTYPE          type,
+                        const char      *file,
+                        unsigned        line)
+{
+    if (op && op->type == type)
+    {
+        return op;
+    }
+    fprintf(stderr,
+            "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
+            " expected %s, got %s\n",
+            macro, args, file, line,
+            opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
+    exit(-1);
+    return op; // never reached, makes compiler happy.
+}