commited Sandeep's ptr inc/dec opts after his disc crashed
[fw/sdcc] / src / ds390 / gen.c
index 9d27211c2a728064c7ef45bfe326a802140c5ef7..ea5009fb7f9b5e6e429095826c17453cba3bc385 100644 (file)
@@ -4,6 +4,7 @@
   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
+  DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
 
   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
@@ -38,6 +39,9 @@
 #ifdef HAVE_SYS_ISA_DEFS_H
 #include <sys/isa_defs.h>
 #else
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #else
@@ -47,6 +51,7 @@
 #endif
 #endif
 #endif
+#endif
 
 #define BETTER_LITERAL_SHIFT
 
@@ -465,7 +470,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
        {
          if (options.model == MODEL_FLAT24)
            emitcode ("mov", "dpx1,#0x40");
-   TR_DPTR("#2");
+         TR_DPTR("#2");
          emitcode ("mov", "dph1,#0x00");
          emitcode ("mov", "dpl1, a");
        }
@@ -506,8 +511,8 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
   if (IS_FUNC (sym->type))
     {
       sym->aop = aop = newAsmop (AOP_IMMD);
-      aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
-      strcpy (aop->aopu.aop_immd, sym->rname);
+      aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
+      strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
       aop->size = FPTRSIZE;
       return aop;
     }
@@ -543,7 +548,7 @@ aopForRemat (symbol * sym)
 {
   iCode *ic = sym->rematiCode;
   asmop *aop = newAsmop (AOP_IMMD);
-
+  int ptr_type =0;
   int val = 0;
 
   for (;;)
@@ -552,9 +557,14 @@ aopForRemat (symbol * sym)
        val += (int) operandLitValue (IC_RIGHT (ic));
       else if (ic->op == '-')
        val -= (int) operandLitValue (IC_RIGHT (ic));
-      else
-       break;
-
+      else if (IS_CAST_ICODE(ic)) {
+             sym_link *from_type = operandType(IC_RIGHT(ic));
+             aop->aopu.aop_immd.from_cast_remat = 1;
+             ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+             ptr_type = DCL_TYPE(from_type);
+             continue ;
+      } else break;
+      
       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
     }
 
@@ -566,8 +576,15 @@ aopForRemat (symbol * sym)
   else
     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
 
-  aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
-  strcpy (aop->aopu.aop_immd, buffer);
+  aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
+  strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
+  /* set immd2 field if required */
+  if (aop->aopu.aop_immd.from_cast_remat) {
+         sprintf(buffer,"#0x%02x",ptr_type);
+         aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
+         strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
+  }
+
   return aop;
 }
 
@@ -983,8 +1000,8 @@ aopGet (asmop * aop,
          genSetDPTR (1);
          if (!canClobberACC)
            {
-       TR_AP("#1");
-             emitcode ("xch", "a, %s", DP2_RESULT_REG);
+                   TR_AP("#1");
+                   emitcode ("xch", "a, %s", DP2_RESULT_REG);
            }
        }
 
@@ -1026,15 +1043,17 @@ aopGet (asmop * aop,
       return (dname ? "acc" : "a");
 
     case AOP_IMMD:
-      if (bit16)
-       sprintf (s, "#%s", aop->aopu.aop_immd);
+      if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
+             sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
+      } else if (bit16)
+       sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
       else if (offset)
        sprintf (s, "#(%s >> %d)",
-                aop->aopu.aop_immd,
+                aop->aopu.aop_immd.aop_immd1,
                 offset * 8);
       else
        sprintf (s, "#%s",
-                aop->aopu.aop_immd);
+                aop->aopu.aop_immd.aop_immd1);
       rs = Safe_calloc (1, strlen (s) + 1);
       strcpy (rs, s);
       return rs;
@@ -1225,7 +1244,12 @@ aopPut (asmop * aop, char *s, int offset)
       if (strcmp (s, "a") == 0)
        emitcode ("push", "acc");
       else
-       emitcode ("push", "%s", s);
+       if (*s=='@') {
+         MOVA(s);
+         emitcode ("push", "acc");
+       } else {
+         emitcode ("push", s);
+       }
 
       break;
 
@@ -1770,8 +1794,8 @@ saveRegisters (iCode * lic)
 
   /* if the registers have been saved already then
      do nothing */
-  if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
-      SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
+  if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
+      IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
     return;
 
   /* find the registers in use at this time
@@ -2182,7 +2206,7 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
 static void
 genCall (iCode * ic)
 {
-  sym_link *detype;
+  sym_link *dtype;
   bool restoreBank = FALSE;
   bool swapBanks = FALSE;
 
@@ -2191,17 +2215,17 @@ genCall (iCode * ic)
   /* if we are calling a not _naked function that is not using
      the same register bank then we need to save the
      destination registers on the stack */
-  detype = getSpec (operandType (IC_LEFT (ic)));
-  if (detype && !SPEC_NAKED(detype) &&
-      (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
-      IS_ISR (currFunc->etype))
+  dtype = operandType (IC_LEFT (ic));
+  if (dtype && !IFFUNC_ISNAKED(dtype) &&
+      (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
+      IFFUNC_ISISR (currFunc->type))
   {
       if (!ic->bankSaved) 
       {
            /* This is unexpected; the bank should have been saved in
             * genFunction.
             */
-          saveRBank (SPEC_BANK (detype), ic, FALSE);
+          saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
           restoreBank = TRUE;
       }
       swapBanks = TRUE;
@@ -2269,7 +2293,7 @@ genCall (iCode * ic)
   if (swapBanks)
   {
         emitcode ("mov", "psw,#0x%02x", 
-           ((SPEC_BANK(detype)) << 3) & 0xff);
+           ((FUNC_REGBANK(dtype)) << 3) & 0xff);
   }
 
   /* make the call */
@@ -2280,7 +2304,7 @@ genCall (iCode * ic)
   if (swapBanks)
   {
        emitcode ("mov", "psw,#0x%02x", 
-          ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
+          ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
   }
 
   /* if we need assign a result value */
@@ -2339,12 +2363,12 @@ genCall (iCode * ic)
     }
 
   /* if we hade saved some registers then unsave them */
-  if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
     unsaveRegisters (ic);
 
   /* if register bank was saved then pop them */
   if (restoreBank)
-    unsaveRBank (SPEC_BANK (detype), ic, FALSE);
+    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2353,8 +2377,9 @@ genCall (iCode * ic)
 static void
 genPcall (iCode * ic)
 {
-  sym_link *detype;
+  sym_link *dtype;
   symbol *rlbl = newiTempLabel (NULL);
+  bool restoreBank=FALSE;
 
   D (emitcode (";", "genPcall ");
     );
@@ -2367,12 +2392,13 @@ genPcall (iCode * ic)
   /* if we are calling a function that is not using
      the same register bank then we need to save the
      destination registers on the stack */
-  detype = getSpec (operandType (IC_LEFT (ic)));
-  if (detype &&
-      IS_ISR (currFunc->etype) &&
-      (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
-    saveRBank (SPEC_BANK (detype), ic, TRUE);
-
+  dtype = operandType (IC_LEFT (ic));
+  if (dtype && !IFFUNC_ISNAKED(dtype) &&
+      IFFUNC_ISISR (currFunc->type) &&
+      (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
+    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
+    restoreBank=TRUE;
+  }
 
   /* push the return address on to the stack */
   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
@@ -2462,14 +2488,12 @@ genPcall (iCode * ic)
     }
 
   /* if register bank was saved then unsave them */
-  if (detype &&
-      (SPEC_BANK (currFunc->etype) !=
-       SPEC_BANK (detype)))
-    unsaveRBank (SPEC_BANK (detype), ic, TRUE);
-
+  if (restoreBank)
+    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
+  
   /* if we hade saved some registers then
      unsave them */
-  if (ic->regsSaved)
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
     unsaveRegisters (ic);
 
 }
@@ -2527,7 +2551,7 @@ static void
 genFunction (iCode * ic)
 {
   symbol *sym;
-  sym_link *fetype;
+  sym_link *ftype;
   bool   switchedPSW = FALSE;
 
   D (emitcode (";", "genFunction "););
@@ -2539,25 +2563,25 @@ genFunction (iCode * ic)
   emitcode (";", "-----------------------------------------");
 
   emitcode ("", "%s:", sym->rname);
-  fetype = getSpec (operandType (IC_LEFT (ic)));
+  ftype = operandType (IC_LEFT (ic));
 
-  if (SPEC_NAKED(fetype))
+  if (IFFUNC_ISNAKED(ftype))
   {
       emitcode(";", "naked function: no prologue.");
       return;
   }
 
   /* if critical function then turn interrupts off */
-  if (SPEC_CRTCL (fetype))
+  if (IFFUNC_ISCRITICAL (ftype))
     emitcode ("clr", "ea");
 
   /* here we need to generate the equates for the
      register bank if required */
-  if (SPEC_BANK (fetype) != rbank)
+  if (FUNC_REGBANK (ftype) != rbank)
     {
       int i;
 
-      rbank = SPEC_BANK (fetype);
+      rbank = FUNC_REGBANK (ftype);
       for (i = 0; i < ds390_nRegs; i++)
        {
          if (strcmp (regs390[i].base, "0") == 0)
@@ -2574,7 +2598,7 @@ genFunction (iCode * ic)
 
   /* if this is an interrupt service routine then
      save acc, b, dpl, dph  */
-  if (IS_ISR (sym->etype))
+  if (IFFUNC_ISISR (sym->type))
     {
 
       if (!inExcludeList ("acc"))
@@ -2603,13 +2627,13 @@ genFunction (iCode * ic)
       /* if this isr has no bank i.e. is going to
          run with bank 0 , then we need to save more
          registers :-) */
-      if (!SPEC_BANK (sym->etype))
+      if (!FUNC_REGBANK (sym->type))
        {
 
          /* if this function does not call any other
             function then we can be economical and
             save only those registers that are used */
-         if (!sym->hasFcall)
+         if (!IFFUNC_HASFCALL(sym->type))
            {
              int i;
 
@@ -2646,7 +2670,7 @@ genFunction (iCode * ic)
             */
            unsigned long banksToSave = 0;
            
-           if (sym->hasFcall)
+           if (IFFUNC_HASFCALL(sym->type))
            {
 
 #define MAX_REGISTER_BANKS 4
@@ -2664,20 +2688,20 @@ genFunction (iCode * ic)
                    
                    if (i->op == CALL)
                    {
-                       sym_link *detype;
+                       sym_link *dtype;
                        
-                       detype = getSpec(operandType (IC_LEFT(i)));
-                       if (detype 
-                        && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
+                       dtype = operandType (IC_LEFT(i));
+                       if (dtype 
+                        && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
                        {
                             /* Mark this bank for saving. */
-                            if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
+                            if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
                             {
-                                werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
+                                werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
                             }
                             else
                             {
-                                banksToSave |= (1 << SPEC_BANK(detype));
+                                banksToSave |= (1 << FUNC_REGBANK(dtype));
                             }
                             
                             /* And note that we don't need to do it in 
@@ -2709,7 +2733,7 @@ genFunction (iCode * ic)
                     */
                    emitcode ("push", "psw");
                    emitcode ("mov", "psw,#0x%02x", 
-                             (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+                             (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
                    switchedPSW = TRUE;
                }
                
@@ -2721,6 +2745,7 @@ genFunction (iCode * ic)
                     }
                }
            }
+           // jwk: this needs a closer look
            SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
        }
     }
@@ -2728,7 +2753,7 @@ genFunction (iCode * ic)
     {
       /* if callee-save to be used for this function
          then save the registers being used in this function */
-      if (sym->calleeSave)
+      if (IFFUNC_CALLEESAVES(sym->type))
        {
          int i;
 
@@ -2750,14 +2775,14 @@ genFunction (iCode * ic)
     }
 
   /* set the register bank to the desired value */
-  if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+  if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
    && !switchedPSW)
     {
       emitcode ("push", "psw");
-      emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+      emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
     }
 
-  if (IS_RENT (sym->etype) || options.stackAuto)
+  if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
     {
 
       if (options.useXstack)
@@ -2816,13 +2841,13 @@ genEndFunction (iCode * ic)
 
   D (emitcode (";", "genEndFunction "););
 
-  if (SPEC_NAKED(sym->etype))
+  if (IFFUNC_ISNAKED(sym->type))
   {
       emitcode(";", "naked function: no epilogue.");
       return;
   }
 
-  if (IS_RENT (sym->etype) || options.stackAuto)
+  if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
     {
       emitcode ("mov", "%s,_bp", spname);
     }
@@ -2838,7 +2863,7 @@ genEndFunction (iCode * ic)
     }
 
 
-  if ((IS_RENT (sym->etype) || options.stackAuto))
+  if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
     {
       if (options.useXstack)
        {
@@ -2854,9 +2879,9 @@ genEndFunction (iCode * ic)
     }
 
   /* restore the register bank  */
-  if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+  if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
   {
-    if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
+    if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
      || !options.useXstack)
     {
         /* Special case of ISR using non-zero bank with useXstack
@@ -2866,19 +2891,19 @@ genEndFunction (iCode * ic)
     }
   }
 
-  if (IS_ISR (sym->etype))
+  if (IFFUNC_ISISR (sym->type))
     {
 
       /* now we need to restore the registers */
       /* if this isr has no bank i.e. is going to
          run with bank 0 , then we need to save more
          registers :-) */
-      if (!SPEC_BANK (sym->etype))
+      if (!FUNC_REGBANK (sym->type))
        {
          /* if this function does not call any other
             function then we can be economical and
             save only those registers that are used */
-         if (!sym->hasFcall)
+         if (!IFFUNC_HASFCALL(sym->type))
            {
              int i;
 
@@ -2910,6 +2935,7 @@ genEndFunction (iCode * ic)
             * Restore any register banks saved by genFunction
             * in reverse order.
             */
+         // jwk: this needs a closer look
            unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
            int ix;
          
@@ -2951,7 +2977,7 @@ genEndFunction (iCode * ic)
       if (!inExcludeList ("acc"))
        emitcode ("pop", "acc");
 
-      if (SPEC_CRTCL (sym->etype))
+      if (IFFUNC_ISCRITICAL (sym->type))
        emitcode ("setb", "ea");
 
       /* if debug then send end of function */
@@ -2971,10 +2997,10 @@ genEndFunction (iCode * ic)
     }
   else
     {
-      if (SPEC_CRTCL (sym->etype))
+      if (IFFUNC_ISCRITICAL (sym->type))
        emitcode ("setb", "ea");
 
-      if (sym->calleeSave)
+      if (IFFUNC_CALLEESAVES(sym->type))
        {
          int i;
 
@@ -3352,6 +3378,8 @@ adjustArithmeticResult (iCode * ic)
     }
 }
 
+#if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
+      // Please don't bring it back without a really good reason.
 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
 // (because all three operands are in far space).
 #define AOP_OP_3(ic) \
@@ -3366,6 +3394,7 @@ adjustArithmeticResult (iCode * ic)
         fprintf(stderr,                                  \
                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
     }
+#endif
 
 // Macro to aopOp all three operands of an ic. If this cannot be done, 
 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
@@ -3913,10 +3942,12 @@ release:
 static void
 genMultbits (operand * left,
             operand * right,
-            operand * result)
+            operand * result,
+            iCode   * ic)
 {
   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
+  aopOp(result, ic, TRUE, FALSE);
   outBitC (result);
 }
 
@@ -3927,18 +3958,12 @@ genMultbits (operand * left,
 static void
 genMultOneByte (operand * left,
                operand * right,
-               operand * result)
+               operand * result,
+               iCode   * ic)
 {
   sym_link *opetype = operandType (result);
   symbol *lbl;
-  int size=AOP_SIZE(result);
 
-  if (size<1 || size>2) {
-    // this should never happen
-      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
-              AOP_SIZE(result), __FILE__, lineno);
-      exit (1);
-  }
 
   /* (if two literals: the value is computed before) */
   /* if one literal, literal on the right */
@@ -3959,8 +3984,22 @@ genMultOneByte (operand * left,
     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
     emitcode ("mul", "ab");
+   
+    _G.accInUse++;
+    aopOp(result, ic, TRUE, FALSE);
+      
+      if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
+      {
+         // this should never happen
+         fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
+                  AOP_SIZE(result), __FILE__, lineno);
+         exit (1);
+      }      
+      
     aopPut (AOP (result), "a", 0);
-    if (size==2) {
+    _G.accInUse--;
+    if (AOP_SIZE(result)==2) 
+    {
       aopPut (AOP (result), "b", 1);
     }
     return;
@@ -4004,11 +4043,22 @@ genMultOneByte (operand * left,
   }
   emitcode ("mul", "ab");
     
+  _G.accInUse++;
+  aopOp(result, ic, TRUE, FALSE);
+    
+  if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
+  {
+    // this should never happen
+      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
+              AOP_SIZE(result), __FILE__, lineno);
+      exit (1);
+  }    
+    
   lbl=newiTempLabel(NULL);
   emitcode ("jnb", "F0,%05d$", lbl->key+100);
   // only ONE op was negative, we have to do a 8/16-bit two's complement
   emitcode ("cpl", "a"); // lsb
-  if (size==1) {
+  if (AOP_SIZE(result)==1) {
     emitcode ("inc", "a");
   } else {
     emitcode ("add", "a,#1");
@@ -4020,11 +4070,172 @@ genMultOneByte (operand * left,
 
   emitcode ("", "%05d$:", lbl->key+100);
   aopPut (AOP (result), "a", 0);
-  if (size==2) {
+  _G.accInUse--;
+  if (AOP_SIZE(result)==2) {
     aopPut (AOP (result), "b", 1);
   }
 }
 
+/*-----------------------------------------------------------------*/
+/* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
+/*-----------------------------------------------------------------*/
+static void genMultTwoByte (operand *left, operand *right, 
+                           operand *result, iCode *ic)
+{
+       sym_link *retype = getSpec(operandType(right));
+       sym_link *letype = getSpec(operandType(left));
+       int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
+       symbol *lbl;
+
+       if (AOP_TYPE (left) == AOP_LIT) {
+               operand *t = right;
+               right = left;
+               left = t;
+       }
+       /* save EA bit in F1 */
+       lbl = newiTempLabel(NULL);
+       emitcode ("setb","F1");
+       emitcode ("jbc","EA,%05d$",lbl->key+100);
+       emitcode ("clr","F1");
+       emitcode("","%05d$:",lbl->key+100);
+
+       /* load up MB with right */
+       if (!umult) {
+               emitcode("clr","F0");
+               if (AOP_TYPE(right) == AOP_LIT) {
+                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       if (val < 0) {
+                               emitcode("setb","F0");
+                               val = -val;
+                       }
+                       emitcode ("mov","mb,#0x%02x",val & 0xff);
+                       emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
+               } else {
+                       lbl = newiTempLabel(NULL);
+                       emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+                       emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+                       emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl","a");
+                       emitcode ("add", "a,#1");
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl", "a"); // msb
+                       emitcode ("addc", "a,#0");
+                       emitcode ("setb","F0");
+                       emitcode ("","%05d$:",lbl->key+100);
+                       emitcode ("mov","mb,b");
+                       emitcode ("mov","mb,a");
+               }
+       } else {
+               emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+       }
+       /* load up MA with left */
+       if (!umult) {
+               lbl = newiTempLabel(NULL);
+               emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+               emitcode ("jnb","acc.7,%05d$",lbl->key+100);
+               emitcode ("xch", "a,b");
+               emitcode ("cpl","a");
+               emitcode ("add", "a,#1");
+               emitcode ("xch", "a,b");
+               emitcode ("cpl", "a"); // msb
+               emitcode ("addc","a,#0");
+               emitcode ("jbc","F0,%05d$",lbl->key+100);
+               emitcode ("setb","F0");
+               emitcode ("","%05d$:",lbl->key+100);
+               emitcode ("mov","ma,b");
+               emitcode ("mov","ma,a");
+       } else {
+               emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+       }
+       /* wait for multiplication to finish */
+       lbl = newiTempLabel(NULL);
+       emitcode("","%05d$:", lbl->key+100);
+       emitcode("mov","a,mcnt1");
+       emitcode("anl","a,#0x80");
+       emitcode("jnz","%05d$",lbl->key+100);
+       
+       freeAsmop (left, NULL, ic, TRUE);
+       freeAsmop (right, NULL, ic,TRUE);
+       aopOp(result, ic, TRUE, FALSE);
+
+       /* if unsigned then simple */   
+       if (umult) {
+               emitcode ("mov","a,ma");
+               if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
+               emitcode ("mov","a,ma");
+               if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
+               aopPut(AOP(result),"ma",1);
+               aopPut(AOP(result),"ma",0);
+       } else {
+               emitcode("push","ma");
+               emitcode("push","ma");
+               emitcode("push","ma");
+               MOVA("ma");
+               /* negate result if needed */
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("add","a,#1");
+               emitcode("","%05d$:", lbl->key+100);
+               if (AOP_TYPE(result) == AOP_ACC)
+               {
+                   D(emitcode(";", "ACC special case."););
+                   /* We know result is the only live aop, and 
+                    * it's obviously not a DPTR2, so AP is available.
+                    */
+                   emitcode("mov", "%s,acc", DP2_RESULT_REG);
+               }
+               else
+               {
+                   aopPut(AOP(result),"a",0);
+               }
+           
+               emitcode("pop","acc");
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("addc","a,#0");
+               emitcode("","%05d$:", lbl->key+100);
+               aopPut(AOP(result),"a",1);
+               emitcode("pop","acc");
+               if (AOP_SIZE(result) >= 3) {
+                       lbl = newiTempLabel(NULL);      
+                       emitcode("jnb","F0,%05d$",lbl->key+100);
+                       emitcode("cpl","a");
+                       emitcode("addc","a,#0");                        
+                       emitcode("","%05d$:", lbl->key+100);
+                       aopPut(AOP(result),"a",2);
+               }
+               emitcode("pop","acc");
+               if (AOP_SIZE(result) >= 4) {
+                       lbl = newiTempLabel(NULL);      
+                       emitcode("jnb","F0,%05d$",lbl->key+100);
+                       emitcode("cpl","a");
+                       emitcode("addc","a,#0");                        
+                       emitcode("","%05d$:", lbl->key+100);
+                       aopPut(AOP(result),"a",3);
+               }
+               if (AOP_TYPE(result) == AOP_ACC)
+               {
+                   /* We stashed the result away above. */
+                   emitcode("mov", "acc,%s", DP2_RESULT_REG);
+               }           
+               
+       }
+       freeAsmop (result, NULL, ic, TRUE);
+
+       /* restore EA bit in F1 */
+       lbl = newiTempLabel(NULL);
+       emitcode ("jnb","F1,%05d$",lbl->key+100);
+       emitcode ("setb","EA");
+       emitcode("","%05d$:",lbl->key+100);
+       return ;
+}
+
 /*-----------------------------------------------------------------*/
 /* genMult - generates code for multiplication                     */
 /*-----------------------------------------------------------------*/
@@ -4038,14 +4249,14 @@ genMult (iCode * ic)
   D (emitcode (";", "genMult "););
 
   /* assign the amsops */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
 
   /* special cases first */
   /* both are bits */
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      genMultbits (left, right, result);
+      genMultbits (left, right, result, ic);
       goto release;
     }
 
@@ -4053,12 +4264,17 @@ genMult (iCode * ic)
   if (AOP_SIZE (left) == 1 &&
       AOP_SIZE (right) == 1)
     {
-      genMultOneByte (left, right, result);
+      genMultOneByte (left, right, result, ic);
       goto release;
     }
 
+  if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
+         /* use the ds390 ARITHMETIC accel UNIT */
+         genMultTwoByte (left, right, result, ic);
+         return ;
+  }
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -4072,7 +4288,8 @@ release:
 static void
 genDivbits (operand * left,
            operand * right,
-           operand * result)
+           operand * result,
+           iCode   * ic)
 {
 
   char *l;
@@ -4081,6 +4298,8 @@ genDivbits (operand * left,
   LOAD_AB_FOR_DIV (left, right, l);
   emitcode ("div", "ab");
   emitcode ("rrc", "a");
+  aopOp(result, ic, TRUE, FALSE);
+    
   aopPut (AOP (result), "c", 0);
 }
 
@@ -4090,24 +4309,33 @@ genDivbits (operand * left,
 static void
 genDivOneByte (operand * left,
               operand * right,
-              operand * result)
+              operand * result,
+              iCode   * ic)
 {
   sym_link *opetype = operandType (result);
   char *l;
   symbol *lbl;
   int size, offset;
 
-  size = AOP_SIZE (result) - 1;
   offset = 1;
   /* signed or unsigned */
   if (SPEC_USIGN (opetype))
     {
-      /* unsigned is easy */
-      LOAD_AB_FOR_DIV (left, right, l);
-      emitcode ("div", "ab");
-      aopPut (AOP (result), "a", 0);
-      while (size--)
-       aopPut (AOP (result), zero, offset++);
+       /* unsigned is easy */
+       LOAD_AB_FOR_DIV (left, right, l);
+       emitcode ("div", "ab");
+
+       _G.accInUse++;
+       aopOp(result, ic, TRUE, FALSE);
+       aopPut (AOP (result), "a", 0);
+       _G.accInUse--;
+
+       size = AOP_SIZE (result) - 1;
+       
+       while (size--)
+       {
+           aopPut (AOP (result), zero, offset++);
+       }
       return;
     }
 
@@ -4158,15 +4386,141 @@ genDivOneByte (operand * left,
   emitcode ("", "%05d$:", (lbl->key + 100));
 
   /* now we are done */
-  aopPut (AOP (result), "b", 0);
-  if (size > 0)
+    _G.accInUse++;
+    aopOp(result, ic, TRUE, FALSE);
+    
+    aopPut (AOP (result), "b", 0);
+    
+    size = AOP_SIZE (result) - 1;
+    
+    if (size > 0)
     {
       emitcode ("mov", "c,b.7");
       emitcode ("subb", "a,acc");
     }
-  while (size--)
-    aopPut (AOP (result), "a", offset++);
+    while (size--)
+    {
+       aopPut (AOP (result), "a", offset++);
+    }
+    _G.accInUse--;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
+/*-----------------------------------------------------------------*/
+static void genDivTwoByte (operand *left, operand *right, 
+                           operand *result, iCode *ic)
+{
+       sym_link *retype = getSpec(operandType(right));
+       sym_link *letype = getSpec(operandType(left));
+       int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
+       symbol *lbl;
+
+       /* save EA bit in F1 */
+       lbl = newiTempLabel(NULL);
+       emitcode ("setb","F1");
+       emitcode ("jbc","EA,%05d$",lbl->key+100);
+       emitcode ("clr","F1");
+       emitcode("","%05d$:",lbl->key+100);
+
+       /* load up MA with left */
+       if (!umult) {
+               emitcode("clr","F0");
+               lbl = newiTempLabel(NULL);
+               emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+               emitcode ("jnb","acc.7,%05d$",lbl->key+100);
+               emitcode ("xch", "a,b");
+               emitcode ("cpl","a");
+               emitcode ("add", "a,#1");
+               emitcode ("xch", "a,b");
+               emitcode ("cpl", "a"); // msb
+               emitcode ("addc","a,#0");
+               emitcode ("setb","F0");
+               emitcode ("","%05d$:",lbl->key+100);
+               emitcode ("mov","ma,b");
+               emitcode ("mov","ma,a");
+       } else {
+               emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+       }
+
+       /* load up MB with right */
+       if (!umult) {
+               if (AOP_TYPE(right) == AOP_LIT) {
+                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       if (val < 0) {
+                               lbl = newiTempLabel(NULL);
+                               emitcode ("jbc","F0,%05d$",lbl->key+100);
+                               emitcode("setb","F0");
+                               emitcode ("","%05d$:",lbl->key+100);
+                               val = -val;
+                       } 
+                       emitcode ("mov","mb,#0x%02x",val & 0xff);                   
+                       emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
+               } else {
+                       lbl = newiTempLabel(NULL);
+                       emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+                       emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+                       emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl","a");
+                       emitcode ("add", "a,#1");
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl", "a"); // msb
+                       emitcode ("addc", "a,#0");
+                       emitcode ("jbc","F0,%05d$",lbl->key+100);
+                       emitcode ("setb","F0");
+                       emitcode ("","%05d$:",lbl->key+100);
+                       emitcode ("mov","mb,b");
+                       emitcode ("mov","mb,a");
+               }
+       } else {
+               emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+       }
 
+       /* wait for multiplication to finish */
+       lbl = newiTempLabel(NULL);
+       emitcode("","%05d$:", lbl->key+100);
+       emitcode("mov","a,mcnt1");
+       emitcode("anl","a,#0x80");
+       emitcode("jnz","%05d$",lbl->key+100);
+       
+       freeAsmop (left, NULL, ic, TRUE);
+       freeAsmop (right, NULL, ic,TRUE);
+       aopOp(result, ic, TRUE, FALSE);
+
+       /* if unsigned then simple */   
+       if (umult) {
+               aopPut(AOP(result),"ma",1);
+               aopPut(AOP(result),"ma",0);
+       } else {
+               emitcode("push","ma");
+               MOVA("ma");
+               /* negate result if needed */
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("add","a,#1");
+               emitcode("","%05d$:", lbl->key+100);
+               aopPut(AOP(result),"a",0);
+               emitcode("pop","acc");
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("addc","a,#0");
+               emitcode("","%05d$:", lbl->key+100);
+               aopPut(AOP(result),"a",1);
+       }
+       freeAsmop (result, NULL, ic, TRUE);
+       /* restore EA bit in F1 */
+       lbl = newiTempLabel(NULL);
+       emitcode ("jnb","F1,%05d$",lbl->key+100);
+       emitcode ("setb","EA");
+       emitcode("","%05d$:",lbl->key+100);
+       return ;
 }
 
 /*-----------------------------------------------------------------*/
@@ -4179,18 +4533,17 @@ genDiv (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
-  D (emitcode (";", "genDiv ");
-    );
+  D (emitcode (";", "genDiv "););
 
   /* assign the amsops */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
 
   /* special cases first */
   /* both are bits */
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      genDivbits (left, right, result);
+      genDivbits (left, right, result, ic);
       goto release;
     }
 
@@ -4198,12 +4551,17 @@ genDiv (iCode * ic)
   if (AOP_SIZE (left) == 1 &&
       AOP_SIZE (right) == 1)
     {
-      genDivOneByte (left, right, result);
+      genDivOneByte (left, right, result, ic);
       goto release;
     }
 
+  if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
+         /* use the ds390 ARITHMETIC accel UNIT */
+         genDivTwoByte (left, right, result, ic);
+         return ;
+  }
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -4216,7 +4574,8 @@ release:
 static void
 genModbits (operand * left,
            operand * right,
-           operand * result)
+           operand * result,
+           iCode   * ic)
 {
 
   char *l;
@@ -4226,6 +4585,7 @@ genModbits (operand * left,
   emitcode ("div", "ab");
   emitcode ("mov", "a,b");
   emitcode ("rrc", "a");
+  aopOp(result, ic, TRUE, FALSE);
   aopPut (AOP (result), "c", 0);
 }
 
@@ -4235,7 +4595,8 @@ genModbits (operand * left,
 static void
 genModOneByte (operand * left,
               operand * right,
-              operand * result)
+              operand * result,
+              iCode   * ic)
 {
   sym_link *opetype = operandType (result);
   char *l;
@@ -4247,6 +4608,7 @@ genModOneByte (operand * left,
       /* unsigned is easy */
       LOAD_AB_FOR_DIV (left, right, l);
       emitcode ("div", "ab");
+      aopOp(result, ic, TRUE, FALSE);  
       aopPut (AOP (result), "b", 0);
       return;
     }
@@ -4299,10 +4661,101 @@ genModOneByte (operand * left,
   emitcode ("", "%05d$:", (lbl->key + 100));
 
   /* now we are done */
+  aopOp(result, ic, TRUE, FALSE);    
   aopPut (AOP (result), "b", 0);
 
 }
 
+/*-----------------------------------------------------------------*/
+/* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
+/*-----------------------------------------------------------------*/
+static void genModTwoByte (operand *left, operand *right, 
+                           operand *result, iCode *ic)
+{
+       sym_link *retype = getSpec(operandType(right));
+       sym_link *letype = getSpec(operandType(left));
+       int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
+       symbol *lbl;
+
+       /* load up MA with left */
+       /* save EA bit in F1 */
+       lbl = newiTempLabel(NULL);
+       emitcode ("setb","F1");
+       emitcode ("jbc","EA,%05d$",lbl->key+100);
+       emitcode ("clr","F1");
+       emitcode("","%05d$:",lbl->key+100);
+
+       if (!umult) {
+               lbl = newiTempLabel(NULL);
+               emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+               emitcode ("jnb","acc.7,%05d$",lbl->key+100);
+               emitcode ("xch", "a,b");
+               emitcode ("cpl","a");
+               emitcode ("add", "a,#1");
+               emitcode ("xch", "a,b");
+               emitcode ("cpl", "a"); // msb
+               emitcode ("addc","a,#0");
+               emitcode ("","%05d$:",lbl->key+100);
+               emitcode ("mov","ma,b");
+               emitcode ("mov","ma,a");
+       } else {
+               emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+       }
+
+       /* load up MB with right */
+       if (!umult) {
+               if (AOP_TYPE(right) == AOP_LIT) {
+                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       if (val < 0) {
+                               val = -val;
+                       } 
+                       emitcode ("mov","mb,#0x%02x",val & 0xff);
+                       emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
+               } else {
+                       lbl = newiTempLabel(NULL);
+                       emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+                       emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+                       emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl","a");
+                       emitcode ("add", "a,#1");
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl", "a"); // msb
+                       emitcode ("addc", "a,#0");
+                       emitcode ("","%05d$:",lbl->key+100);
+                       emitcode ("mov","mb,b");
+                       emitcode ("mov","mb,a");
+               }
+       } else {
+               emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+       }
+
+       /* wait for multiplication to finish */
+       lbl = newiTempLabel(NULL);
+       emitcode("","%05d$:", lbl->key+100);
+       emitcode("mov","a,mcnt1");
+       emitcode("anl","a,#0x80");
+       emitcode("jnz","%05d$",lbl->key+100);
+       
+       freeAsmop (left, NULL, ic, TRUE);
+       freeAsmop (right, NULL, ic,TRUE);
+       aopOp(result, ic, TRUE, FALSE);
+
+       aopPut(AOP(result),"mb",1);
+       aopPut(AOP(result),"mb",0);
+       freeAsmop (result, NULL, ic, TRUE);
+
+       /* restore EA bit in F1 */
+       lbl = newiTempLabel(NULL);
+       emitcode ("jnb","F1,%05d$",lbl->key+100);
+       emitcode ("setb","EA");
+       emitcode("","%05d$:",lbl->key+100);
+       return ;
+}
+
 /*-----------------------------------------------------------------*/
 /* genMod - generates code for division                            */
 /*-----------------------------------------------------------------*/
@@ -4313,18 +4766,17 @@ genMod (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
-  D (emitcode (";", "genMod ");
-    );
+  D (emitcode (";", "genMod "); );
 
   /* assign the amsops */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
 
   /* special cases first */
   /* both are bits */
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      genModbits (left, right, result);
+      genModbits (left, right, result, ic);
       goto release;
     }
 
@@ -4332,12 +4784,18 @@ genMod (iCode * ic)
   if (AOP_SIZE (left) == 1 &&
       AOP_SIZE (right) == 1)
     {
-      genModOneByte (left, right, result);
+      genModOneByte (left, right, result, ic);
       goto release;
     }
 
+  if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
+         /* use the ds390 ARITHMETIC accel UNIT */
+         genModTwoByte (left, right, result, ic);
+         return ;
+  }
+
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -4915,6 +5373,39 @@ ifxForOp (operand * op, iCode * ic)
 
   return NULL;
 }
+/*-----------------------------------------------------------------*/
+/* hasInc - operand is incremented before any other use            */
+/*-----------------------------------------------------------------*/
+static iCode *
+hasInc (operand *op, iCode *ic)
+{
+  sym_link *type = operandType(op);
+  sym_link *retype = getSpec (type);
+  iCode *lic = ic->next;
+  int isize ;
+  
+  /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
+  if (!IS_SYMOP(op)) return NULL;
+
+  if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
+  isize = getSize(type->next);
+  while (lic) {
+    /* if operand of the form op = op + <sizeof *op> */
+    if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
+       isOperandEqual(IC_RESULT(lic),op) && 
+       isOperandLiteral(IC_RIGHT(lic)) &&
+       operandLitValue(IC_RIGHT(lic)) == isize) {
+      return lic;
+    }
+    /* if the operand used or deffed */
+    if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
+      return NULL;
+    }
+    lic = lic->next;
+  }
+  return NULL;
+}
+
 /*-----------------------------------------------------------------*/
 /* genAndOp - for && operation                                     */
 /*-----------------------------------------------------------------*/
@@ -5157,8 +5648,11 @@ genAnd (iCode * ic, iCode * ifx)
 #endif
 
   /* if left is a literal & right is not then exchange them */
-  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
+#ifdef LOGIC_OPS_BROKEN      
+    ||  AOP_NEEDSACC (left)
+#endif
+    )
     {
       operand *tmp = right;
       right = left;
@@ -5413,8 +5907,7 @@ genAnd (iCode * ic, iCode * ifx)
                      aopPut (AOP (result), zero, offset);
                      continue;
                    }
-                 D (emitcode (";", "better literal AND.");
-                   );
+                 D (emitcode (";", "better literal AND."););
                  MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
                  emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
                                                    FALSE, FALSE, FALSE));
@@ -5431,10 +5924,16 @@ genAnd (iCode * ic, iCode * ifx)
                    }
                  else
                    {
-                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
-                     emitcode ("anl", "a,%s",
-                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
-                   }
+                     char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
+                     if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
+                     {
+                         emitcode("mov", "b,a");
+                         rOp = "b";
+                     }
+                       
+                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
+                     emitcode ("anl", "a,%s", rOp);
+                   }                   
                }
              aopPut (AOP (result), "a", offset);
            }
@@ -5481,8 +5980,11 @@ genOr (iCode * ic, iCode * ifx)
 #endif
 
   /* if left is a literal & right is not then exchange them */
-  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
+#ifdef LOGIC_OPS_BROKEN
+   || AOP_NEEDSACC (left) // I think this is a net loss now.
+#endif      
+      )
     {
       operand *tmp = right;
       right = left;
@@ -5702,6 +6204,7 @@ genOr (iCode * ic, iCode * ifx)
        }
       else
        {
+           _startLazyDPSEvaluation();
          for (; (size--); offset++)
            {
              // normal case
@@ -5715,8 +6218,7 @@ genOr (iCode * ic, iCode * ifx)
                              offset);
                      continue;
                    }
-                 D (emitcode (";", "better literal OR.");
-                   );
+                 D (emitcode (";", "better literal OR."););
                  MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
                  emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
                                                    FALSE, FALSE, FALSE));
@@ -5733,13 +6235,21 @@ genOr (iCode * ic, iCode * ifx)
                    }
                  else
                    {
-                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
-                     emitcode ("orl", "a,%s",
-                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+                     char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
+                       
+                     if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
+                     {
+                         emitcode("mov", "b,a");
+                         rOp = "b";
+                     }
+                       
+                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
+                     emitcode ("orl", "a,%s", rOp);
                    }
                }
              aopPut (AOP (result), "a", offset);
            }
+           _endLazyDPSEvaluation();
        }
     }
 
@@ -5782,8 +6292,11 @@ genXor (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not ||
      if left needs acc & right does not */
-  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
+#ifdef LOGIC_OPS_BROKEN      
+      || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
+#endif
+     )
     {
       operand *tmp = right;
       right = left;
@@ -6011,9 +6524,15 @@ genXor (iCode * ic, iCode * ifx)
                  }
                else
                  {
-                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
-                   emitcode ("xrl", "a,%s",
-                          aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
+                     char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
+                     if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
+                     {
+                         emitcode("mov", "b,a");
+                         rOp = "b";
+                     }
+                       
+                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
+                     emitcode ("xrl", "a,%s", rOp);
                  }
              }
            aopPut (AOP (result), "a", offset);
@@ -8051,7 +8570,8 @@ genDataPointerGet (operand * left,
 static void
 genNearPointerGet (operand * left,
                   operand * result,
-                  iCode * ic)
+                  iCode * ic,
+                  iCode *pi)
 {
   asmop *aop = NULL;
   regs *preg = NULL;
@@ -8120,7 +8640,7 @@ genNearPointerGet (operand * left,
              aopPut (AOP (result), buffer, offset);
            }
          offset++;
-         if (size)
+         if (size || pi)
            emitcode ("inc", "%s", rname);
        }
     }
@@ -8129,6 +8649,9 @@ genNearPointerGet (operand * left,
   if (aop)
     {
       /* we had to allocate for this iCode */
+      if (pi) { /* post increment present */
+       aopPut(AOP ( left ),rname,0);
+      }
       freeAsmop (NULL, aop, ic, TRUE);
     }
   else
@@ -8141,7 +8664,8 @@ genNearPointerGet (operand * left,
       if (AOP_SIZE (result) > 1 &&
          !OP_SYMBOL (left)->remat &&
          (OP_SYMBOL (left)->liveTo > ic->seq ||
-          ic->depth))
+          ic->depth) &&
+         !pi)
        {
          int size = AOP_SIZE (result) - 1;
          while (size--)
@@ -8151,7 +8675,7 @@ genNearPointerGet (operand * left,
 
   /* done */
   freeAsmop (result, NULL, ic, TRUE);
-
+  if (pi) pi->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
@@ -8160,7 +8684,8 @@ genNearPointerGet (operand * left,
 static void
 genPagedPointerGet (operand * left,
                    operand * result,
-                   iCode * ic)
+                   iCode * ic,
+                   iCode * pi)
 {
   asmop *aop = NULL;
   regs *preg = NULL;
@@ -8207,7 +8732,7 @@ genPagedPointerGet (operand * left,
 
          offset++;
 
-         if (size)
+         if (size || pi)
            emitcode ("inc", "%s", rname);
        }
     }
@@ -8216,6 +8741,7 @@ genPagedPointerGet (operand * left,
   if (aop)
     {
       /* we had to allocate for this iCode */
+      if (pi) aopPut ( AOP (left), rname, 0);
       freeAsmop (NULL, aop, ic, TRUE);
     }
   else
@@ -8228,7 +8754,8 @@ genPagedPointerGet (operand * left,
       if (AOP_SIZE (result) > 1 &&
          !OP_SYMBOL (left)->remat &&
          (OP_SYMBOL (left)->liveTo > ic->seq ||
-          ic->depth))
+          ic->depth) &&
+         !pi)
        {
          int size = AOP_SIZE (result) - 1;
          while (size--)
@@ -8238,8 +8765,7 @@ genPagedPointerGet (operand * left,
 
   /* done */
   freeAsmop (result, NULL, ic, TRUE);
-
-
+  if (pi) pi->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
@@ -8247,7 +8773,7 @@ genPagedPointerGet (operand * left,
 /*-----------------------------------------------------------------*/
 static void
 genFarPointerGet (operand * left,
-                 operand * result, iCode * ic)
+                 operand * result, iCode * ic, iCode *pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (result));
@@ -8312,13 +8838,20 @@ genFarPointerGet (operand * left,
          _flushLazyDPS ();
 
          emitcode ("movx", "a,@dptr");
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
 
          aopPut (AOP (result), "a", offset++);
        }
       _endLazyDPSEvaluation ();
     }
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+    aopPut ( AOP (left), "dpl", 0);
+    aopPut ( AOP (left), "dph", 1);
+    if (options.model == MODEL_FLAT24)
+           aopPut ( AOP (left), "dpx", 2);
+    pi->generated = 1;
+  }
 
   freeAsmop (result, NULL, ic, TRUE);
 }
@@ -8328,7 +8861,7 @@ genFarPointerGet (operand * left,
 /*-----------------------------------------------------------------*/
 static void
 emitcodePointerGet (operand * left,
-                   operand * result, iCode * ic)
+                   operand * result, iCode * ic, iCode *pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (result));
@@ -8370,7 +8903,6 @@ emitcodePointerGet (operand * left,
        }
     }
   /* so dptr know contains the address */
-  freeAsmop (left, NULL, ic, TRUE);
   aopOp (result, ic, FALSE, TRUE);
 
   /* if bit then unpack */
@@ -8389,13 +8921,21 @@ emitcodePointerGet (operand * left,
 
          emitcode ("clr", "a");
          emitcode ("movc", "a,@a+dptr");
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
          aopPut (AOP (result), "a", offset++);
        }
       _endLazyDPSEvaluation ();
     }
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+    aopPut ( AOP (left), "dpl", 0);
+    aopPut ( AOP (left), "dph", 1);
+    if (options.model == MODEL_FLAT24)
+           aopPut ( AOP (left), "dpx", 2);
+    pi->generated = 1;
+  }
 
+  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
 }
 
@@ -8404,7 +8944,7 @@ emitcodePointerGet (operand * left,
 /*-----------------------------------------------------------------*/
 static void
 genGenPointerGet (operand * left,
-                 operand * result, iCode * ic)
+                 operand * result, iCode * ic, iCode * pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (result));
@@ -8422,7 +8962,10 @@ genGenPointerGet (operand * left,
       if (AOP_TYPE (left) == AOP_IMMD)
        {
          emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
-         emitcode ("mov", "b,#%d", pointerCode (retype));
+         if (AOP(left)->aopu.aop_immd.from_cast_remat) 
+                 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
+         else
+                 emitcode ("mov", "b,#%d", pointerCode (retype));
        }
       else
        {                       /* we need to get it byte by byte */
@@ -8460,7 +9003,6 @@ genGenPointerGet (operand * left,
        }
     }
   /* so dptr know contains the address */
-  freeAsmop (left, NULL, ic, TRUE);
   aopOp (result, ic, FALSE, TRUE);
 
   /* if bit then unpack */
@@ -8475,11 +9017,21 @@ genGenPointerGet (operand * left,
        {
          emitcode ("lcall", "__gptrget");
          aopPut (AOP (result), "a", offset++);
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
        }
     }
 
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+    aopPut ( AOP (left), "dpl", 0);
+    aopPut ( AOP (left), "dph", 1);
+    if (options.model == MODEL_FLAT24) {
+           aopPut ( AOP (left), "dpx", 2);
+           aopPut ( AOP (left), "b", 3);       
+    } else  aopPut ( AOP (left), "b", 2);      
+    pi->generated = 1;
+  }
+  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
 }
 
@@ -8487,7 +9039,7 @@ genGenPointerGet (operand * left,
 /* genPointerGet - generate code for pointer get                   */
 /*-----------------------------------------------------------------*/
 static void
-genPointerGet (iCode * ic)
+genPointerGet (iCode * ic, iCode *pi)
 {
   operand *left, *result;
   sym_link *type, *etype;
@@ -8511,7 +9063,13 @@ genPointerGet (iCode * ic)
       /* we have to go by the storage class */
       p_type = PTR_TYPE (SPEC_OCLS (etype));
     }
-
+  /* special case when cast remat */
+  if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
+      IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
+         left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
+         type =   type = operandType (left);
+         p_type = DCL_TYPE (type);
+  }
   /* now that we have the pointer type we assign
      the pointer values */
   switch (p_type)
@@ -8519,23 +9077,23 @@ genPointerGet (iCode * ic)
 
     case POINTER:
     case IPOINTER:
-      genNearPointerGet (left, result, ic);
+      genNearPointerGet (left, result, ic, pi);
       break;
 
     case PPOINTER:
-      genPagedPointerGet (left, result, ic);
+      genPagedPointerGet (left, result, ic, pi);
       break;
 
     case FPOINTER:
-      genFarPointerGet (left, result, ic);
+      genFarPointerGet (left, result, ic, pi);
       break;
 
     case CPOINTER:
-      emitcodePointerGet (left, result, ic);
+      emitcodePointerGet (left, result, ic, pi);
       break;
 
     case GPOINTER:
-      genGenPointerGet (left, result, ic);
+      genGenPointerGet (left, result, ic, pi);
       break;
     }
 
@@ -9029,7 +9587,10 @@ genGenPointerSet (operand * right,
       if (AOP_TYPE (result) == AOP_IMMD)
        {
          emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
-         emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
+         if (AOP(result)->aopu.aop_immd.from_cast_remat) 
+                 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
+         else
+                 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
        }
       else
        {                       /* we need to get it byte by byte */
@@ -9079,7 +9640,7 @@ genGenPointerSet (operand * right,
 /* genPointerSet - stores the value into a pointer location        */
 /*-----------------------------------------------------------------*/
 static void
-genPointerSet (iCode * ic)
+genPointerSet (iCode * ic, iCode *pi)
 {
   operand *right, *result;
   sym_link *type, *etype;
@@ -9105,6 +9666,13 @@ genPointerSet (iCode * ic)
       /* we have to go by the storage class */
       p_type = PTR_TYPE (SPEC_OCLS (etype));
     }
+  /* special case when cast remat */
+  if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
+      IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
+         result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
+         type =   type = operandType (result);
+         p_type = DCL_TYPE (type);
+  }
 
   /* now that we have the pointer type we assign
      the pointer values */
@@ -9259,6 +9827,7 @@ genArrayInit (iCode * ic)
     int         elementSize = 0, eIndex;
     unsigned    val, lastVal;
     sym_link    *type;
+    operand     *left=IC_LEFT(ic);
     
     D (emitcode (";", "genArrayInit "););
 
@@ -9272,9 +9841,17 @@ genArrayInit (iCode * ic)
     }
     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
     {
-       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-               "Unexpected operand to genArrayInit.\n");
-       exit(1);
+#if 0
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "Unexpected operand to genArrayInit.\n");
+      exit(1);
+#else
+      // a regression because of SDCCcse.c:1.52
+      emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
+      emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
+      if (options.model == MODEL_FLAT24)
+       emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
+#endif
     }
     
     type = operandType(IC_LEFT(ic));
@@ -9491,9 +10068,8 @@ genAssign (iCode * ic)
     goto release;
 
   /* if the result is a bit */
-  if (AOP_TYPE (result) == AOP_CRY)
+  if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
     {
-
       /* if the right size is a literal then
          we know what the value is */
       if (AOP_TYPE (right) == AOP_LIT)
@@ -9624,7 +10200,8 @@ genCast (iCode * ic)
   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
 
   /* if the result is a bit */
-  if (AOP_TYPE (result) == AOP_CRY)
+  // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
+  if (IS_BITVAR(OP_SYMBOL(result)->type))
     {
       /* if the right size is a literal then
          we know what the value is */
@@ -10177,12 +10754,12 @@ gen390Code (iCode * lic)
          break;
 
        case GET_VALUE_AT_ADDRESS:
-         genPointerGet (ic);
+         genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
          break;
 
        case '=':
          if (POINTER_SET (ic))
-           genPointerSet (ic);
+           genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
          else
            genAssign (ic);
          break;