Buffer overflow hunt: removing strcpy, strcat, sprintf
[fw/sdcc] / src / ds390 / gen.c
index e110942ee7b82423f78badd79f62d517c0a64b82..1cf40126b348e97bf7c6490a1f18184af97ec885 100644 (file)
@@ -30,7 +30,7 @@
 #include <string.h>
 #include <ctype.h>
 
-#include <common.h>
+#include "common.h"
 #include "ralloc.h"
 #include "gen.h"
 #include "SDCCglobl.h"
 #define BETTER_LITERAL_SHIFT
 
 char *aopLiteral (value * val, int offset);
+extern int allocInfo;
 
 /* this is the down and dirty file with all kinds of
    kludgy & hacky stuff. This is what it is all about
    CODE GENERATION for a specific MCU . some of the
    routines may be reusable, will have to see */
 
-static char *zero = "#0x00";
-static char *one = "#0x01";
+static char *zero = "#0";
+static char *one = "#1";
 static char *spname;
 
 #define D(x) x
@@ -79,6 +80,7 @@ static char *fReturn16[] =
 static char **fReturn = fReturn24;
 static char *accUse[] =
 {"a", "b"};
+static char *dptrn[2][3];
 static char *javaRet[] = { "r0","r1","r2","r3"};
 static short rbank = -1;
 
@@ -91,10 +93,16 @@ static struct
     short inLine;
     short debugLine;
     short nRegsSaved;
+    short dptrInUse;
+    short dptr1InUse;
     set *sendSet;
   }
 _G;
 
+static char *rb1regs[] = {
+    "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
+};
+
 static void saveRBank (int, iCode *, bool);
 
 #define RESULTONSTACK(x) \
@@ -130,6 +138,20 @@ static unsigned char SRMask[] =
 #define MSB16   1
 #define MSB24   2
 #define MSB32   3
+#define PROTECT_SP     {if (options.protect_sp_update) {                       \
+                               symbol *lbl = newiTempLabel(NULL);              \
+                               emitcode ("setb","F1");                         \
+                               emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
+                               emitcode ("clr","F1");                          \
+                               emitcode ("","!tlabeldef",lbl->key+100);        \
+                       }}
+#define UNPROTECT_SP   { if (options.protect_sp_update) {                      \
+                               symbol *lbl = newiTempLabel(NULL);              \
+                               emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
+                               emitcode ("setb","EA");                         \
+                               emitcode ("","!tlabeldef",lbl->key+100);        \
+                       }}
+
 
 /*-----------------------------------------------------------------*/
 /* emitcode - writes the code into a file : for now it is simple    */
@@ -137,33 +159,47 @@ static unsigned char SRMask[] =
 static void
 emitcode (char *inst, char *fmt,...)
 {
-  va_list ap;
-  char lb[INITIAL_INLINEASM];
-  char *lbp = lb;
-
-  va_start (ap, fmt);
-
-  if (inst && *inst)
+    va_list ap;
+    char lb[INITIAL_INLINEASM];
+    char *lbp = lb;
+    
+    va_start (ap, fmt);
+    
+    if (inst && *inst)
     {
-      if (fmt && *fmt)
-       sprintf (lb, "%s\t", inst);
-      else
-       sprintf (lb, "%s", inst);
-      tvsprintf (lb + (strlen (lb)), fmt, ap);
+       if (fmt && *fmt)
+       {
+           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
+       }
+       else
+       {
+           SNPRINTF (lb, sizeof(lb), "%s", inst);
+       }
+       
+       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
+                  fmt, ap);
     }
-  else
-    tvsprintf (lb, fmt, ap);
+    else
+    {
+       tvsprintf (lb, sizeof(lb), fmt, ap);
+    }
+    
 
-  while (isspace (*lbp))
-    lbp++;
+    while (isspace (*lbp))
+    {
+       lbp++;
+    }
 
-  if (lbp && *lbp)
-    lineCurr = (lineCurr ?
-               connectLine (lineCurr, newLineNode (lb)) :
-               (lineHead = newLineNode (lb)));
-  lineCurr->isInline = _G.inLine;
-  lineCurr->isDebug = _G.debugLine;
-  va_end (ap);
+    if (lbp && *lbp)
+    {
+       lineCurr = (lineCurr ?
+                   connectLine (lineCurr, newLineNode (lb)) :
+                   (lineHead = newLineNode (lb)));
+    }
+    
+    lineCurr->isInline = _G.inLine;
+    lineCurr->isDebug = _G.debugLine;
+    va_end (ap);
 }
 
 /*-----------------------------------------------------------------*/
@@ -460,49 +496,77 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
 
   if (sym->onStack && options.stack10bit)
     {
+       short stack_val = -((sym->stack < 0) ?
+                           ((short) (sym->stack - _G.nRegsSaved)) :
+                           ((short) sym->stack)) ;
+       if (useDP2 && _G.dptr1InUse) {
+           emitcode ("push","dpl1");
+           emitcode ("push","dph1");
+           emitcode ("push","dpx1");
+       } else if (_G.dptrInUse ) {
+           emitcode ("push","dpl");
+           emitcode ("push","dph");
+           emitcode ("push","dpx");
+       }
       /* It's on the 10 bit stack, which is located in
        * far data space.
-       */
-
-      if (_G.accInUse)
-       emitcode ("push", "acc");
-
-      if (_G.bInUse)
-       emitcode ("push", "b");
-
-      emitcode ("mov", "a,_bpx");
-      emitcode ("clr","c");
-      emitcode ("subb", "a,#!constbyte",
-               -((sym->stack < 0) ?
-                 ((short) (sym->stack - _G.nRegsSaved)) :
-                 ((short) sym->stack)) & 0xff);
-      emitcode ("mov","b,a");
-      emitcode ("mov","a,_bpx+1");
-      emitcode ("subb","a,#!constbyte",(-((sym->stack < 0) ?
-                                    ((short) (sym->stack - _G.nRegsSaved)) :
-                                    ((short) sym->stack)) >> 8) & 0xff);
-      if (useDP2) {
-         if (options.model == MODEL_FLAT24)
-             emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
-         TR_DPTR("#2");
-         emitcode ("mov", "dph1,a");
-         emitcode ("mov", "dpl1,b");
-      } else {
-         if (options.model == MODEL_FLAT24)
-             emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
-         emitcode ("mov", "dph,a");
-         emitcode ("mov", "dpl,b");
-      }
-
-      if (_G.bInUse)
-       emitcode ("pop", "b");
-
-      if (_G.accInUse)
-       emitcode ("pop", "acc");
-
-      sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
-      aop->size = getSize (sym->type);
-      return aop;
+       */          
+       if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
+           if (useDP2) {
+               if (options.model == MODEL_FLAT24)
+                   emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
+               TR_DPTR("#2");
+               emitcode ("mov", "dph1,_bpx+1");
+               emitcode ("mov", "dpl1,_bpx");
+               emitcode ("mov","dps,#1");
+           } else {
+               if (options.model == MODEL_FLAT24)
+                   emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
+               emitcode ("mov", "dph,_bpx+1");
+               emitcode ("mov", "dpl,_bpx");
+           }
+           stack_val = -stack_val;
+           while (stack_val--) {
+               emitcode ("inc","dptr");
+           }
+           if (useDP2) {
+               emitcode("mov","dps,#0");
+           }
+       }  else {
+           if (_G.accInUse)
+               emitcode ("push", "acc");
+           
+           if (_G.bInUse)
+               emitcode ("push", "b");
+       
+           emitcode ("mov", "a,_bpx");
+           emitcode ("clr","c");
+           emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
+           emitcode ("mov","b,a");
+           emitcode ("mov","a,_bpx+1");
+           emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
+           if (useDP2) {
+               if (options.model == MODEL_FLAT24)
+                   emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
+               TR_DPTR("#2");
+               emitcode ("mov", "dph1,a");
+               emitcode ("mov", "dpl1,b");
+           } else {
+               if (options.model == MODEL_FLAT24)
+                   emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
+               emitcode ("mov", "dph,a");
+               emitcode ("mov", "dpl,b");
+           }
+           
+           if (_G.bInUse)
+               emitcode ("pop", "b");
+           
+           if (_G.accInUse)
+               emitcode ("pop", "acc");
+       }
+       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
+       aop->size = getSize (sym->type);
+       return aop;
     }
 
   /* if in bit space */
@@ -531,7 +595,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
       aop->size = FPTRSIZE;
       return aop;
     }
-
+  
   /* only remaining is far space */
   /* in which case DPTR gets the address */
   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
@@ -592,16 +656,20 @@ aopForRemat (symbol * sym)
             OP_SYMBOL (IC_LEFT (ic))->rname,
             val >= 0 ? '+' : '-',
             abs (val) & 0xffff);
-  else
-    strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
+  else {
+      if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
+         sprintf(buffer,"0x%x",(int) operandLitValue (IC_RIGHT (ic)));
+      else
+         strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
+  }
 
   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) {
-         tsprintf(buffer,"#!constbyte",ptr_type);
-         aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
-         strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
+  if (aop->aopu.aop_immd.from_cast_remat) 
+  {
+      tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
+      aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);  
   }
 
   return aop;
@@ -833,7 +901,7 @@ aopOp (operand * op, iCode * ic, bool result, bool useDP2)
              /* a AOP_STR uses DPTR, but DPTR is already in use;
               * we're just hosed.
               */
-             fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
+               werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
            }
 
          aop = op->aop = sym->aop = newAsmop (AOP_STR);
@@ -842,7 +910,13 @@ aopOp (operand * op, iCode * ic, bool result, bool useDP2)
            aop->aopu.aop_str[i] = fReturn[i];
          return;
        }
-
+      
+      if (sym->dptr) { /* has been allocated to a DPTRn */
+         aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
+         aop->size = getSize (sym->type);
+         aop->aopu.dptr = sym->dptr;
+         return ;
+      }
       /* else spill location  */
       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
          /* force a new aop if sizes differ */
@@ -961,8 +1035,21 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
            _G.r1Pushed--;
          }
       }
+    case AOP_DPTR2:
+       if (_G.dptr1InUse) {
+           emitcode ("pop","dpx1");
+           emitcode ("pop","dph1");
+           emitcode ("pop","dpl1");
+       }
+       break;
+    case AOP_DPTR:
+       if (_G.dptrInUse) {
+           emitcode ("pop","dpx");
+           emitcode ("pop","dph");
+           emitcode ("pop","dpl");
+       }
+       break;
     }
-
 dealloc:
   /* all other cases just dealloc */
   if (op)
@@ -993,8 +1080,8 @@ aopGet (asmop * aop,
        bool dname,
        bool canClobberACC)
 {
-  char *s = buffer;
-  char *rs;
+  //char *s = buffer;
+  //char *rs;
 
   /* offset is greater than
      size then zero */
@@ -1027,10 +1114,12 @@ aopGet (asmop * aop,
          emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
          return (dname ? "acc" : "a");
        }
-      sprintf (s, "@%s", aop->aopu.aop_ptr->name);
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+      SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
+      return Safe_strdup(buffer);      
+
+    case AOP_DPTRn:
+       assert(offset <= 3);
+       return dptrn[aop->aopu.dptr][offset];
 
     case AOP_DPTR:
     case AOP_DPTR2:
@@ -1083,44 +1172,60 @@ aopGet (asmop * aop,
       return (dname ? "acc" : "a");
 
     case 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) {
+      if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
+      {
+         SNPRINTF(buffer, sizeof(buffer), 
+                  "%s",aop->aopu.aop_immd.aop_immd2);
+      } 
+      else if (bit16)
+      {
+        SNPRINTF(buffer, sizeof(buffer), 
+                 "#%s", aop->aopu.aop_immd.aop_immd1);
+      }
+      else if (offset) 
+      {
          switch (offset) {
          case 1:
-             tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
+             tsprintf(buffer, sizeof(buffer),
+                      "#!his",aop->aopu.aop_immd.aop_immd1);
              break;
          case 2:
-             tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
+             tsprintf(buffer, sizeof(buffer), 
+                      "#!hihis",aop->aopu.aop_immd.aop_immd1);
              break;
          case 3:
-             tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
+             tsprintf(buffer, sizeof(buffer),
+                      "#!hihihis",aop->aopu.aop_immd.aop_immd1);
              break;
          default: /* should not need this (just in case) */
-             sprintf (s, "#(%s >> %d)",
+             SNPRINTF (buffer, sizeof(buffer), 
+                       "#(%s >> %d)",
                       aop->aopu.aop_immd.aop_immd1,
                       offset * 8);
          }
       }
       else
-       sprintf (s, "#%s",
-                aop->aopu.aop_immd.aop_immd1);
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+      {
+       SNPRINTF (buffer, sizeof(buffer), 
+                 "#%s", aop->aopu.aop_immd.aop_immd1);
+      }
+      return Safe_strdup(buffer);      
 
     case AOP_DIR:
       if (offset)
-       sprintf (s, "(%s + %d)",
+      {
+       SNPRINTF (buffer, sizeof(buffer),
+                 "(%s + %d)",
                 aop->aopu.aop_dir,
                 offset);
+      }
       else
-       sprintf (s, "%s", aop->aopu.aop_dir);
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+      {
+       SNPRINTF(buffer, sizeof(buffer), 
+                "%s", aop->aopu.aop_dir);
+      }
+
+      return Safe_strdup(buffer);
 
     case AOP_REG:
       if (dname)
@@ -1208,6 +1313,10 @@ aopPut (asmop * aop, char *s, int offset)
        }
       break;
 
+    case AOP_DPTRn:
+       emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
+       break;
+
     case AOP_DPTR:
     case AOP_DPTR2:
 
@@ -1328,11 +1437,8 @@ aopPut (asmop * aop, char *s, int offset)
                  MOVA (s);
                }
              {
-               symbol *lbl = newiTempLabel (NULL);
-               emitcode ("clr", "c");
-               emitcode ("jz", "!tlabel", lbl->key + 100);
-               emitcode ("cpl", "c");
-               emitcode ("", "!tlabeldef", lbl->key + 100);
+               /* set C, if a >= 1 */
+               emitcode ("add", "a,#!constbyte",0xff);
                emitcode ("mov", "%s,c", aop->aopu.aop_dir);
              }
            }
@@ -1415,6 +1521,8 @@ reAdjustPreg (asmop * aop)
 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
+#define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
+#define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
 
 /* Workaround for DS80C390 bug: div ab may return bogus results
  * if A is accessed in instruction immediately before the div.
@@ -1673,6 +1781,7 @@ genCpl (iCode * ic)
 {
   int offset = 0;
   int size;
+  symbol *tlbl;
 
   D (emitcode (";", "genCpl ");
     );
@@ -1682,17 +1791,21 @@ genCpl (iCode * ic)
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
 
-  /* if both are in bit space then
-     a special case */
-  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
-      AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
-    {
-
+  /* special case if in bit space */
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
+    if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
       emitcode ("cpl", "c");
       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
       goto release;
     }
+    tlbl=newiTempLabel(NULL);
+    emitcode ("cjne", "%s,#0x01,%05d$", 
+             aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
+    emitcode ("", "%05d$:", tlbl->key+100);
+    outBitC (IC_RESULT(ic));
+    goto release;
+  }
 
   size = AOP_SIZE (IC_RESULT (ic));
   _startLazyDPSEvaluation ();
@@ -1887,6 +2000,7 @@ saveRegisters (iCode * lic)
          if (bitVectBitValue(ic->rMask,i))
              rsave = bitVectSetBit(rsave,i);
       }
+      rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
   } else {
     /* safe the registers in use at this time but skip the
        ones for the result */
@@ -1941,6 +2055,7 @@ unsaveRegisters (iCode * ic)
          if (bitVectBitValue(ic->rMask,i))
              rsave = bitVectSetBit(rsave,i);
       }
+      rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
   } else {
     /* restore the registers in use at this time but skip the
        ones for the result */
@@ -2052,7 +2167,7 @@ genIpush (iCode * ic)
     {
 
       /* and the item is spilt then do nothing */
-      if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+      if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
        return;
 
       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
@@ -2124,7 +2239,7 @@ genIpop (iCode * ic)
 
 
   /* if the temp was not pushed then */
-  if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+  if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
     return;
 
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
@@ -2273,6 +2388,56 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
   }
 }
 
+/*-----------------------------------------------------------------*/
+/* genSend - gen code for SEND                                    */
+/*-----------------------------------------------------------------*/
+static void genSend(set *sendSet)
+{
+    iCode *sic;
+    int sendCount = 0 ;
+    static int rb1_count = 0;
+
+    for (sic = setFirstItem (sendSet); sic;
+        sic = setNextItem (sendSet)) {     
+       int size, offset = 0;
+       
+       size=getSize(operandType(IC_LEFT(sic)));
+       D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
+       if (sendCount == 0) { /* first parameter */
+           // we know that dpl(hxb) is the result, so
+           rb1_count = 0 ;
+           _startLazyDPSEvaluation ();
+           if (size>1) {
+               aopOp (IC_LEFT (sic), sic, FALSE, 
+                      (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
+           } else {
+               aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
+           }
+           while (size--) {
+               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
+                                 FALSE, FALSE, TRUE);
+               if (strcmp (l, fReturn[offset])) {
+                   emitcode ("mov", "%s,%s",
+                             fReturn[offset],
+                             l);
+               }
+               offset++;
+           }
+           _endLazyDPSEvaluation ();
+           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+           rb1_count =0;
+       } else { /* if more parameter in registers */
+           aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
+           while (size--) {
+               emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
+                                                               FALSE, FALSE, TRUE));
+           }
+           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+       }
+       sendCount++;
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
@@ -2316,74 +2481,10 @@ genCall (iCode * ic)
   */
   if (_G.sendSet)
     {
-      iCode *sic;
-
-      for (sic = setFirstItem (_G.sendSet); sic;
-          sic = setNextItem (_G.sendSet))
-       {
-         int size, offset = 0;
-
-#if 0
-         aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
-         size = AOP_SIZE (IC_LEFT (sic));
-
-         _startLazyDPSEvaluation ();
-         while (size--)
-           {
-             char *l = aopGet (AOP(IC_LEFT(sic)), offset,
-                               FALSE, FALSE, TRUE);
-               if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
-               {
-                   emitcode("mov", "%s,%s", regs390[offset].name, l);
-               }
-               else if (strcmp (l, fReturn[offset]))
-               {
-                   emitcode ("mov", "%s,%s",
-                             fReturn[offset],
-                             l);
-               }
-             offset++;
-           }
-         _endLazyDPSEvaluation ();
-         if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
-         {
-             size = AOP_SIZE (IC_LEFT (sic));
-             if (size)
-             {
-                size--;
-             }
-             while (size)
-             {
-                  size--;
-                  emitcode("mov", "%s,%s",
-                                   fReturn[size], regs390[size].name);
-             }
-         }
-#else
-         // we know that dpl(hxb) is the result, so
-         _startLazyDPSEvaluation ();
-         size=getSize(operandType(IC_LEFT(sic)));
-         if (size>1) {
-           aopOp (IC_LEFT (sic), sic, FALSE, 
-                  (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
-         } else {
-           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
-         }
-         while (size--)
-           {
-             char *l = aopGet (AOP (IC_LEFT (sic)), offset,
-                               FALSE, FALSE, TRUE);
-             if (strcmp (l, fReturn[offset]))
-               {
-                 emitcode ("mov", "%s,%s",
-                           fReturn[offset],
-                           l);
-               }
-             offset++;
-           }
-         _endLazyDPSEvaluation ();
-#endif
-         freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+       if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
+           genSend(reverseSet(_G.sendSet));
+       } else {
+           genSend(_G.sendSet);
        }
       _G.sendSet = NULL;
     }  
@@ -2448,16 +2549,26 @@ genCall (iCode * ic)
   /* adjust the stack for parameters if
      required */
   if (ic->parmBytes) {
+      int i;
       if (options.stack10bit) {
-         emitcode ("clr","c");
-         emitcode ("mov","a,sp");
-         emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
-         emitcode ("mov","sp,a");
-         emitcode ("mov","a,esp");
-         emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
-         emitcode ("mov","esp,a");       
+         if (ic->parmBytes <= 10) {
+             emitcode(";","stack adjustment for parms");
+             for (i=0; i < ic->parmBytes ; i++) {
+                 emitcode("pop","acc");
+             }
+         } else {            
+             PROTECT_SP;
+             emitcode ("clr","c");
+             emitcode ("mov","a,sp");
+             emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
+             emitcode ("mov","sp,a");
+             emitcode ("mov","a,esp");
+             emitcode ("anl","a,#3");
+             emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
+             emitcode ("mov","esp,a");   
+             UNPROTECT_SP;
+         }
       } else {
-         int i;
          if (ic->parmBytes > 3) {
              emitcode ("mov", "a,%s", spname);
              emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
@@ -2528,37 +2639,8 @@ genPcall (iCode * ic)
   /* if send set is not empty the assign */
   if (_G.sendSet)
     {
-      iCode *sic;
-
-      for (sic = setFirstItem (_G.sendSet); sic;
-          sic = setNextItem (_G.sendSet))
-       {
-         int size, offset = 0;
-
-         // we know that dpl(hxb) is the result, so
-         _startLazyDPSEvaluation ();
-         size=getSize(operandType(IC_LEFT(sic)));
-         if (size>1) {
-           aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
-         } else {
-           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
-         }
-         while (size--)
-           {
-             char *l = aopGet (AOP (IC_LEFT (sic)), offset,
-                               FALSE, FALSE, TRUE);
-             if (strcmp (l, fReturn[offset]))
-               {
-                 emitcode ("mov", "%s,%s",
-                           fReturn[offset],
-                           l);
-               }
-             offset++;
-           }
-         _endLazyDPSEvaluation ();
-         freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
-       }
-      _G.sendSet = NULL;
+       genSend(reverseSet(_G.sendSet));
+       _G.sendSet = NULL;
     }
 
   emitcode ("ret", "");
@@ -2586,18 +2668,36 @@ genPcall (iCode * ic)
   if (ic->parmBytes)
     {
       int i;
-      if (ic->parmBytes > 3)
-       {
-         emitcode ("mov", "a,%s", spname);
-         emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
-         emitcode ("mov", "%s,a", spname);
-       }
-      else
-       for (i = 0; i < ic->parmBytes; i++)
-         emitcode ("dec", "%s", spname);
-
+      if (options.stack10bit) {
+         if (ic->parmBytes <= 10) {
+             emitcode(";","stack adjustment for parms");
+             for (i=0; i < ic->parmBytes ; i++) {
+                 emitcode("pop","acc");
+             }
+         } else {            
+             PROTECT_SP;
+             emitcode ("clr","c");
+             emitcode ("mov","a,sp");
+             emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
+             emitcode ("mov","sp,a");
+             emitcode ("mov","a,esp");
+             emitcode ("anl","a,#3");
+             emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
+             emitcode ("mov","esp,a");   
+             UNPROTECT_SP;
+         }
+      } else {
+         if (ic->parmBytes > 3) {
+             emitcode ("mov", "a,%s", spname);
+             emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
+             emitcode ("mov", "%s,a", spname);
+         }
+         else
+             for (i = 0; i < ic->parmBytes; i++)
+                 emitcode ("dec", "%s", spname);
+         
+      }
     }
-
   /* if register bank was saved then unsave them */
   if (restoreBank)
     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
@@ -2714,8 +2814,7 @@ genFunction (iCode * ic)
   /* if this is an interrupt service routine then
      save acc, b, dpl, dph  */
   if (IFFUNC_ISISR (sym->type))
-    {
-
+      { /* is ISR */
       if (!inExcludeList ("acc"))
        emitcode ("push", "acc");
       if (!inExcludeList ("b"))
@@ -2744,13 +2843,13 @@ genFunction (iCode * ic)
          registers :-) */
       if (!FUNC_REGBANK (sym->type))
        {
+           int i;
 
          /* if this function does not call any other
             function then we can be economical and
             save only those registers that are used */
          if (!IFFUNC_HASFCALL(sym->type))
            {
-             int i;
 
              /* if any registers used */
              if (sym->regsUsed)
@@ -2771,6 +2870,11 @@ genFunction (iCode * ic)
                 determines register usage so we will have to push the
                 entire bank */
              saveRBank (0, ic, FALSE);
+             if (options.parms_in_bank1) {
+                 for (i=0; i < 8 ; i++ ) {
+                     emitcode ("push","%s",rb1regs[i]);
+                 }
+             }
            }
        }
        else
@@ -2923,14 +3027,21 @@ genFunction (iCode * ic)
   if (sym->stack) {
       int i = sym->stack;
       if (options.stack10bit) {
-         if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
+         if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
          assert (sym->recvSize <= 4);
-         emitcode ("mov","a,sp");
-         emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
-         emitcode ("mov","sp,a");
-         emitcode ("mov","a,esp");
-         emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
-         emitcode ("mov","esp,a");
+         if (sym->stack <= 8) {
+             while (i--) emitcode ("push","acc");
+         } else {
+             PROTECT_SP;
+             emitcode ("mov","a,sp");
+             emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
+             emitcode ("mov","sp,a");
+             emitcode ("mov","a,esp");
+             emitcode ("anl","a,#3");
+             emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
+             emitcode ("mov","esp,a");
+             UNPROTECT_SP;
+         }
       } else {
          if (i > 256)
              werror (W_STACK_OVERFLOW, sym->name);
@@ -2977,8 +3088,10 @@ genEndFunction (iCode * ic)
        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
 
       if (options.stack10bit) {
+         PROTECT_SP;     
          emitcode ("mov", "sp,_bpx", spname);
          emitcode ("mov", "esp,_bpx+1", spname);
+         UNPROTECT_SP;
       } else {
          emitcode ("mov", "%s,_bp", spname);
       }
@@ -3023,10 +3136,10 @@ genEndFunction (iCode * ic)
          */
         emitcode ("pop", "psw");
     }
-  }
+  } 
 
   if (IFFUNC_ISISR (sym->type))
-    {
+      { /* is ISR */  
 
       /* now we need to restore the registers */
       /* if this isr has no bank i.e. is going to
@@ -3034,12 +3147,12 @@ genEndFunction (iCode * ic)
          registers :-) */
       if (!FUNC_REGBANK (sym->type))
        {
+           int i;
          /* if this function does not call any other
             function then we can be economical and
             save only those registers that are used */
          if (!IFFUNC_HASFCALL(sym->type))
            {
-             int i;
 
              /* if any registers used */
              if (sym->regsUsed)
@@ -3059,6 +3172,11 @@ genEndFunction (iCode * ic)
              /* this function has  a function call cannot
                 determines register usage so we will have to pop the
                 entire bank */
+             if (options.parms_in_bank1) {
+                 for (i = 7 ; i >= 0 ; i-- ) {
+                     emitcode ("pop","%s",rb1regs[i]);
+                 }
+             }
              unsaveRBank (0, ic, FALSE);
            }
        }
@@ -3320,6 +3438,13 @@ findLabelBackwards (iCode * ic, int key)
       ic = ic->prev;
       count++;
 
+      /* If we have any pushes or pops, we cannot predict the distance.
+        I don't like this at all, this should be dealt with in the 
+        back-end */
+      if (ic->op == IPUSH || ic->op == IPOP) {
+       return 0;
+      }
+
       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
        {
          /* printf("findLabelBackwards = %d\n", count); */
@@ -3350,6 +3475,13 @@ genPlusIncr (iCode * ic)
   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
     return FALSE;
 
+  if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
+      AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
+      while (icount--) {
+         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
+      }
+      return TRUE;
+  }
   /* if increment 16 bits in register */
   if (
        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
@@ -3431,6 +3563,32 @@ genPlusIncr (iCode * ic)
       return TRUE;
     }
 
+  if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
+      !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
+      options.model == MODEL_FLAT24 ) {
+
+      switch (size) {
+      case 3:
+         emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, FALSE));
+      case 2:
+         emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, FALSE));
+      case 1:
+         emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
+         break;
+      }
+      while (icount--) emitcode ("inc","dptr");      
+      return TRUE;
+  }
+
+  if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
+      AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
+      icount <= 5 ) {
+      emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
+      while (icount--) emitcode ("inc","dptr");
+      emitcode ("mov","dps,#0");
+      return TRUE;
+  }
+
   /* if the sizes are greater than 1 then we cannot */
   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
       AOP_SIZE (IC_LEFT (ic)) > 1)
@@ -3550,24 +3708,7 @@ 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) \
-    aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
-    aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
-    aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
-              (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
-        AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
-    { \
-        /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
-        fprintf(stderr,                                  \
-               "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
-    }
-#endif
-
+#ifdef KEVIN_SCREWED_UP
 // 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
 // will be set TRUE. The caller must then handle the case specially, noting
@@ -3575,9 +3716,9 @@ adjustArithmeticResult (iCode * ic)
 #define AOP_OP_3_NOFATAL(ic, rc) \
     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
-                                  (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
+                                  ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
-        (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
+        (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
     { \
        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
        rc = TRUE; \
@@ -3601,40 +3742,122 @@ adjustArithmeticResult (iCode * ic)
     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
 
-// convienience macro.
-#define AOP_SET_LOCALS(ic) \
-    left = IC_LEFT(ic); \
-    right = IC_RIGHT(ic); \
-    result = IC_RESULT(ic);
+#else // Kevin didn't screw up...
 
+#define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
 
-// Given an integer value of pushedSize bytes on the stack,
-// adjust it to be resultSize bytes, either by discarding
-// the most significant bytes or by zero-padding.
-//
-// On exit from this macro, pushedSize will have been adjusted to
-// equal resultSize, and ACC may be trashed.
-#define ADJUST_PUSHED_RESULT(pushedSize, resultSize)           \
-      /* If the pushed data is bigger than the result,         \
-       * simply discard unused bytes. Icky, but works.         \
-       */                                                      \
-      while (pushedSize > resultSize)                          \
-      {                                                                \
-         D (emitcode (";", "discarding unused result byte."););\
-         emitcode ("pop", "acc");                              \
-         pushedSize--;                                         \
-      }                                                                \
-      if (pushedSize < resultSize)                             \
-      {                                                                \
-         emitcode ("clr", "a");                                \
-         /* Conversly, we haven't pushed enough here.          \
-          * just zero-pad, and all is well.                    \
-          */                                                   \
-         while (pushedSize < resultSize)                       \
-         {                                                     \
-             emitcode("push", "acc");                          \
-             pushedSize++;                                     \
-         }                                                     \
+// The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
+// generates the result if possible. If result is generated, returns TRUE; otherwise
+// returns false and caller must deal with fact that result isn't aopOp'd.
+bool aopOp3(iCode * ic)
+{
+    bool dp1InUse, dp2InUse;
+    
+    // First, generate the right opcode. DPTR may be used if neither left nor result are
+    // of type AOP_STR.
+    
+//    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
+//            AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
+//            AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
+//            AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
+//      );
+    
+    aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
+    
+    // Now, the left opcode. This can use DPTR if the right didn't AND the result is not
+    // AOP_STR (however, if the result is the same operand as the left, then DPTR may be used).
+    aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)) ||
+                                  (AOP_IS_STR(IC_RESULT(ic)) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))));
+    
+    // We've op'd the left. So, if left & result are the same operand, we know aopOp
+    // will succeed, and we can just do it & bail.
+    if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
+    {
+//     D(emitcode(";", "aopOp3: left & result equal"););
+       aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
+       return TRUE;
+    }
+    
+    // Note which dptrs are currently in use.
+    dp1InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) ||
+               AOP_IS_STR(IC_RIGHT(ic)) || AOP_IS_STR(IC_LEFT(ic));
+    dp2InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2);
+    
+    // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot generate it.
+    if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
+    {
+       return FALSE;
+    }
+    
+    // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
+    if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
+    {
+       return FALSE;
+    }
+
+    aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
+
+    // SOme sanity checking...
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 &&
+       AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2)
+    {
+       fprintf(stderr,
+               "Ack: got unexpected DP2! (%s:%d %s:%d)\n",
+               __FILE__, __LINE__, ic->filename, ic->lineno);  
+    }
+       
+    return TRUE;
+}
+
+// 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
+// will be set TRUE. The caller must then handle the case specially, noting
+// that the IC_RESULT operand is not aopOp'd.
+// 
+#define AOP_OP_3_NOFATAL(ic, rc) \
+           do { rc = !aopOp3(ic); } while (0)
+
+// aopOp the left & right operands of an ic.
+#define AOP_OP_2(ic) \
+    aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
+    aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
+
+#endif
+
+// convienience macro.
+#define AOP_SET_LOCALS(ic) \
+    left = IC_LEFT(ic); \
+    right = IC_RIGHT(ic); \
+    result = IC_RESULT(ic);
+
+
+// Given an integer value of pushedSize bytes on the stack,
+// adjust it to be resultSize bytes, either by discarding
+// the most significant bytes or by zero-padding.
+//
+// On exit from this macro, pushedSize will have been adjusted to
+// equal resultSize, and ACC may be trashed.
+#define ADJUST_PUSHED_RESULT(pushedSize, resultSize)           \
+      /* If the pushed data is bigger than the result,         \
+       * simply discard unused bytes. Icky, but works.         \
+       */                                                      \
+      while (pushedSize > resultSize)                          \
+      {                                                                \
+         D (emitcode (";", "discarding unused result byte."););\
+         emitcode ("pop", "acc");                              \
+         pushedSize--;                                         \
+      }                                                                \
+      if (pushedSize < resultSize)                             \
+      {                                                                \
+         emitcode ("clr", "a");                                \
+         /* Conversly, we haven't pushed enough here.          \
+          * just zero-pad, and all is well.                    \
+          */                                                   \
+         while (pushedSize < resultSize)                       \
+         {                                                     \
+             emitcode("push", "acc");                          \
+             pushedSize++;                                     \
+         }                                                     \
       }                                                                \
       assert(pushedSize == resultSize);
 
@@ -3850,6 +4073,13 @@ genMinusDec (iCode * ic)
   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
     return FALSE;
 
+  if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
+      AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
+      while (icount--) {
+         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
+      }
+      return TRUE;
+  }
   /* if decrement 16 bits in register */
   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
@@ -4034,9 +4264,11 @@ genMinus (iCode * ic)
   D (emitcode (";", "genMinus "););
 
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
-  aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
+  aopOp (IC_RIGHT (ic), ic, FALSE, 
+        (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
-      (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
+      ((AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2)
+       || OP_SYMBOL(IC_RESULT(ic))->ruonly))
     {
       pushResult = TRUE;
     }
@@ -4075,40 +4307,42 @@ genMinus (iCode * ic)
 
   /* if literal, add a,#-lit, else normal subb */
   _startLazyDPSEvaluation ();
-  while (size--)
-    {
+  while (size--) {
       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
-      if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
-       emitcode ("subb", "a,%s",
-                 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
-      else
-       {
+      if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
+         if (AOP_USESDPTR(IC_RIGHT(ic))) {
+             emitcode ("mov","b,a");
+             MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
+             emitcode ("xch","a,b");
+             emitcode ("subb","a,b");
+         } else {
+             emitcode ("subb", "a,%s",
+                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
+         }
+      } else {
          /* first add without previous c */
          if (!offset) {
-           if (!size && lit==-1) {
-             emitcode ("dec", "a");
-           } else {
-             emitcode ("add", "a,#!constbyte",
-                       (unsigned int) (lit & 0x0FFL));
-           }
+             if (!size && lit==-1) {
+                 emitcode ("dec", "a");
+             } else {
+                 emitcode ("add", "a,#!constbyte",
+                           (unsigned int) (lit & 0x0FFL));
+             }
          } else {
-           emitcode ("addc", "a,#!constbyte",
-                     (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+             emitcode ("addc", "a,#!constbyte",
+                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
          }
-       }
-
-      if (pushResult)
-       {
+      }
+      
+      if (pushResult) {
          emitcode ("push", "acc");
-       }
-      else
-       {
+      } else {
          aopPut (AOP (IC_RESULT (ic)), "a", offset);
-       }
+      }
       offset++;
-    }
+  }
   _endLazyDPSEvaluation ();
-
+  
   if (pushResult)
     {
       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
@@ -5076,7 +5310,7 @@ genCmp (operand * left, operand * right,
 
       /* if unsigned char cmp with lit, do cjne left,#right,zz */
       if ((size == 1) && !sign &&
-         (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
+         (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
        {
          symbol *lbl = newiTempLabel (NULL);
          emitcode ("cjne", "%s,%s,!tlabel",
@@ -5579,7 +5813,7 @@ ifxForOp (operand * op, iCode * ic)
 /* hasInc - operand is incremented before any other use            */
 /*-----------------------------------------------------------------*/
 static iCode *
-hasInc (operand *op, iCode *ic)
+hasInc (operand *op, iCode *ic, int osize)
 {
   sym_link *type = operandType(op);
   sym_link *retype = getSpec (type);
@@ -5590,7 +5824,9 @@ hasInc (operand *op, iCode *ic)
   if (!IS_SYMOP(op)) return NULL;
 
   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
-  isize = getSize(type->next);
+  if (IS_AGGREGATE(type->next)) return NULL;
+  if (osize != (isize = getSize(type->next))) return NULL;
+
   while (lic) {
       /* if operand of the form op = op + <sizeof *op> */
       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
@@ -5964,6 +6200,10 @@ genAnd (iCode * ic, iCode * ifx)
                  sprintf (buffer, "acc.%d", posbit & 0x07);
                  genIfxJump (ifx, buffer);
                }
+             else 
+                 {
+                     emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
+                 }
              goto release;
            }
        }
@@ -8356,11 +8596,11 @@ genRightShiftLiteral (operand * left,
        default:
          break;
        }
-
-      freeAsmop (left, NULL, ic, TRUE);
-      freeAsmop (result, NULL, ic, TRUE);
     }
-    return TRUE;
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  
+  return TRUE;
 }
 #endif
 
@@ -8998,7 +9238,7 @@ genFarPointerGet (operand * left,
 
   /* if the operand is already in dptr
      then we do nothing else we move the value to dptr */
-  if (AOP_TYPE (left) != AOP_STR)
+  if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
     {
       /* if this is remateriazable */
       if (AOP_TYPE (left) == AOP_IMMD)
@@ -9033,42 +9273,70 @@ genFarPointerGet (operand * left,
        }
     }
   /* so dptr know contains the address */
-  aopOp (result, ic, FALSE, TRUE);
+  aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
-    genUnpackBits (result, "dptr", FPOINTER);
-  else
+  if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(AOP(left)->aopu.dptr);
+      }
+      genUnpackBits (result, "dptr", FPOINTER);
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(0);
+      }
+  } else
     {
       size = AOP_SIZE (result);
       offset = 0;
 
-      _startLazyDPSEvaluation ();
-      while (size--)
-       {
-
-         genSetDPTR (0);
-         _flushLazyDPS ();
-
-         emitcode ("movx", "a,@dptr");
-         if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
-           emitcode ("inc", "dptr");
-
-         aopPut (AOP (result), "a", offset++);
-       }
-      _endLazyDPSEvaluation ();
+      if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
+         while (size--) {
+             genSetDPTR(AOP(left)->aopu.dptr);
+             emitcode ("movx", "a,@dptr");
+             if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
+                 emitcode ("inc", "dptr");
+             genSetDPTR (0);
+             aopPut (AOP (result), "a", offset++);
+         }
+      } else {
+         _startLazyDPSEvaluation ();
+         while (size--) {
+             if (AOP_INDPTRn(left)) {
+                 genSetDPTR(AOP(left)->aopu.dptr);
+             } else {
+                 genSetDPTR (0);
+             }
+             _flushLazyDPS ();
+             
+             emitcode ("movx", "a,@dptr");
+             if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
+                 emitcode ("inc", "dptr");
+             
+             aopPut (AOP (result), "a", offset++);
+         }
+         _endLazyDPSEvaluation ();
+      }
     }
   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
-    aopPut ( AOP (left), "dpl", 0);
-    aopPut ( AOP (left), "dph", 1);
-    if (options.model == MODEL_FLAT24)
-           aopPut ( AOP (left), "dpx", 2);
+      if (!AOP_INDPTRn(left)) {
+         aopPut ( AOP (left), "dpl", 0);
+         aopPut ( AOP (left), "dph", 1);
+         if (options.model == MODEL_FLAT24)
+             aopPut ( AOP (left), "dpx", 2);
+      }
     pi->generated = 1;
-  } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
+  } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
+            AOP_SIZE(result) > 1 &&
             (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
       
       size = AOP_SIZE (result) - 1;
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(AOP(left)->aopu.dptr);
+      }
       while (size--) emitcode ("lcall","__decdptr");
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(0);
+      }
   }
 
   freeAsmop (left, NULL, ic, TRUE);
@@ -9076,10 +9344,10 @@ genFarPointerGet (operand * left,
 }
 
 /*-----------------------------------------------------------------*/
-/* emitcodePointerGet - gget value from code space                  */
+/* genCodePointerGet - get value from code space                  */
 /*-----------------------------------------------------------------*/
 static void
-emitcodePointerGet (operand * left,
+genCodePointerGet (operand * left,
                    operand * result, iCode * ic, iCode *pi)
 {
   int size, offset, dopi=1;
@@ -9089,7 +9357,7 @@ emitcodePointerGet (operand * left,
 
   /* if the operand is already in dptr
      then we do nothing else we move the value to dptr */
-  if (AOP_TYPE (left) != AOP_STR)
+  if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
     {
       /* if this is remateriazable */
       if (AOP_TYPE (left) == AOP_IMMD)
@@ -9123,41 +9391,71 @@ emitcodePointerGet (operand * left,
        }
     }
   /* so dptr know contains the address */
-  aopOp (result, ic, FALSE, TRUE);
+  aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype))
-    genUnpackBits (result, "dptr", CPOINTER);
-  else
+  if (IS_BITVAR (retype)) {
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(AOP(left)->aopu.dptr);
+      }
+      genUnpackBits (result, "dptr", CPOINTER);
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(0);
+      }
+  } else
     {
       size = AOP_SIZE (result);
       offset = 0;
-
-      _startLazyDPSEvaluation ();
-      while (size--)
-       {
-         genSetDPTR (0);
-         _flushLazyDPS ();
-
-         emitcode ("clr", "a");
-         emitcode ("movc", "a,@a+dptr");
-         if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
-           emitcode ("inc", "dptr");
-         aopPut (AOP (result), "a", offset++);
-       }
-      _endLazyDPSEvaluation ();
+      if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
+         while (size--) {
+             genSetDPTR(AOP(left)->aopu.dptr);
+             emitcode ("clr", "a");
+             emitcode ("movc", "a,@a+dptr");
+             if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
+                 emitcode ("inc", "dptr");
+             genSetDPTR (0);
+             aopPut (AOP (result), "a", offset++);
+         }
+      } else {
+         _startLazyDPSEvaluation ();
+         while (size--)
+             {
+                 if (AOP_INDPTRn(left)) {
+                     genSetDPTR(AOP(left)->aopu.dptr);
+                 } else {
+                     genSetDPTR (0);
+                 }
+                 _flushLazyDPS ();
+                 
+                 emitcode ("clr", "a");
+                 emitcode ("movc", "a,@a+dptr");
+                 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
+                     emitcode ("inc", "dptr");
+                 aopPut (AOP (result), "a", offset++);
+             }
+         _endLazyDPSEvaluation ();
+      }
     }
   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
-      aopPut ( AOP (left), "dpl", 0);
-      aopPut ( AOP (left), "dph", 1);
-      if (options.model == MODEL_FLAT24)
-         aopPut ( AOP (left), "dpx", 2);
+      if (!AOP_INDPTRn(left)) {
+         aopPut ( AOP (left), "dpl", 0);
+         aopPut ( AOP (left), "dph", 1);
+         if (options.model == MODEL_FLAT24)
+             aopPut ( AOP (left), "dpx", 2);
+      }
       pi->generated = 1;
-  } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
+  } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
+            AOP_SIZE(result) > 1 &&
             (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
       
       size = AOP_SIZE (result) - 1;
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(AOP(left)->aopu.dptr);
+      }
       while (size--) emitcode ("lcall","__decdptr");
+      if (AOP_INDPTRn(left)) {
+         genSetDPTR(0);
+      }
   }
   
   freeAsmop (left, NULL, ic, TRUE);
@@ -9195,6 +9493,8 @@ genGenPointerGet (operand * left,
       else
        {                       /* we need to get it byte by byte */
          _startLazyDPSEvaluation ();
+#if 0  // I see no point at all to this code.
+       // So I yanked it. Kill at some future date if no bugs rear their heads.
          if (AOP(left)->type==AOP_DPTR2) {
            char *l;
            l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
@@ -9214,7 +9514,10 @@ genGenPointerGet (operand * left,
            } else {
              emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
            }
-         } else {
+         } 
+         else 
+#endif         
+         {
            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) {
@@ -9227,23 +9530,48 @@ genGenPointerGet (operand * left,
          _endLazyDPSEvaluation ();
        }
     }
-  /* so dptr know contains the address */
+
+  /* so dptr-b now contains the address */
+  _G.bInUse++;
   aopOp (result, ic, FALSE, TRUE);
+  _G.bInUse--;
 
   /* if bit then unpack */
   if (IS_BITVAR (retype) || IS_BITVAR (letype))
+  {
     genUnpackBits (result, "dptr", GPOINTER);
+  }
   else
     {
-      size = AOP_SIZE (result);
-      offset = 0;
+       size = AOP_SIZE (result);
+       offset = 0;
 
-      while (size--)
+       while (size--)
        {
-         emitcode ("lcall", "__gptrget");
-         aopPut (AOP (result), "a", offset++);
-         if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
-           emitcode ("inc", "dptr");
+           if (size)
+           {
+               // Get two bytes at a time, results in _AP & A.
+               // dptr will be incremented ONCE by __gptrgetWord.
+               //
+               // Note: any change here must be coordinated
+               // with the implementation of __gptrgetWord
+               // in device/lib/_gptrget.c
+               emitcode ("lcall", "__gptrgetWord");
+               aopPut (AOP (result), DP2_RESULT_REG, offset++);
+               aopPut (AOP (result), "a", offset++);
+               size--;
+           }
+           else
+           {
+               // Only one byte to get.
+               emitcode ("lcall", "__gptrget");
+               aopPut (AOP (result), "a", offset++);
+           }
+           
+           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
+           {
+               emitcode ("inc", "dptr");
+           }
        }
     }
 
@@ -9298,7 +9626,7 @@ genPointerGet (iCode * ic, iCode *pi)
   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);
+         type = operandType (left);
          p_type = DCL_TYPE (type);
   }
   /* now that we have the pointer type we assign
@@ -9320,7 +9648,7 @@ genPointerGet (iCode * ic, iCode *pi)
       break;
 
     case CPOINTER:
-      emitcodePointerGet (left, result, ic, pi);
+      genCodePointerGet (left, result, ic, pi);
       break;
 
     case GPOINTER:
@@ -9742,7 +10070,7 @@ genFarPointerSet (operand * right,
 
   /* if the operand is already in dptr
      then we do nothing else we move the value to dptr */
-  if (AOP_TYPE (result) != AOP_STR)
+  if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
     {
       /* if this is remateriazable */
       if (AOP_TYPE (result) == AOP_IMMD)
@@ -9775,43 +10103,72 @@ genFarPointerSet (operand * right,
        }
     }
   /* so dptr know contains the address */
-  aopOp (right, ic, FALSE, TRUE);
+  aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
-    genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
-  else
-    {
+  if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
+      if (AOP_INDPTRn(result)) {
+         genSetDPTR(AOP(result)->aopu.dptr);
+      }
+      genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
+      if (AOP_INDPTRn(result)) {
+         genSetDPTR(0);
+      }
+  } else {
       size = AOP_SIZE (right);
       offset = 0;
-
-      _startLazyDPSEvaluation ();
-      while (size--)
-       {
-         char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
-         MOVA (l);
-
-         genSetDPTR (0);
-         _flushLazyDPS ();
-
-         emitcode ("movx", "@dptr,a");
-         if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
-           emitcode ("inc", "dptr");
-       }
-      _endLazyDPSEvaluation ();
-    }
-
+      if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
+         while (size--) {
+             char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
+             MOVA (l);
+             
+             genSetDPTR(AOP(result)->aopu.dptr);
+             emitcode ("movx", "@dptr,a");
+             if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
+                 emitcode ("inc", "dptr");
+             genSetDPTR (0);
+         }
+      } else {
+         _startLazyDPSEvaluation ();
+         while (size--) {
+             char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
+             MOVA (l);
+             
+             if (AOP_INDPTRn(result)) {
+                 genSetDPTR(AOP(result)->aopu.dptr);
+             } else {
+                 genSetDPTR (0);
+             }
+             _flushLazyDPS ();
+             
+             emitcode ("movx", "@dptr,a");
+             if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
+                 emitcode ("inc", "dptr");
+         }
+         _endLazyDPSEvaluation ();
+      }
+  }
+  
   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
-      aopPut (AOP(result),"dpl",0);
-      aopPut (AOP(result),"dph",1);
-      if (options.model == MODEL_FLAT24)
-         aopPut (AOP(result),"dpx",2);
+      if (!AOP_INDPTRn(result)) {
+         aopPut (AOP(result),"dpl",0);
+         aopPut (AOP(result),"dph",1);
+         if (options.model == MODEL_FLAT24)
+             aopPut (AOP(result),"dpx",2);
+      }
       pi->generated=1;
-  } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
+  } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
+            AOP_SIZE(right) > 1 &&
             (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
       
       size = AOP_SIZE (right) - 1;
+      if (AOP_INDPTRn(result)) {
+         genSetDPTR(AOP(result)->aopu.dptr);
+      } 
       while (size--) emitcode ("lcall","__decdptr");
+      if (AOP_INDPTRn(result)) {
+         genSetDPTR(0);
+      }
   }
   freeAsmop (result, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
@@ -9938,7 +10295,7 @@ genPointerSet (iCode * ic, iCode *pi)
   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);
+         type = operandType (result);
          p_type = DCL_TYPE (type);
   }
 
@@ -9963,7 +10320,11 @@ genPointerSet (iCode * ic, iCode *pi)
     case GPOINTER:
       genGenPointerSet (right, result, ic, pi);
       break;
-    }
+
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+             "genPointerSet: illegal pointer type");
+    }
 
 }
 
@@ -10026,16 +10387,17 @@ genAddrOf (iCode * ic)
       /* if 10 bit stack */
       if (options.stack10bit) {
          char buff[10];
-         tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
+         tsprintf(buff, sizeof(buff), 
+                  "#!constbyte",(options.stack_loc >> 16) & 0xff);
          /* if it has an offset then we need to compute it */
-         emitcode ("subb", "a,#!constbyte",
-                   -((sym->stack < 0) ?
-                     ((short) (sym->stack - _G.nRegsSaved)) :
-                     ((short) sym->stack)) & 0xff);
-         emitcode ("mov","b,a");
-         emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
-                                        ((short) (sym->stack - _G.nRegsSaved)) :
-                                        ((short) sym->stack)) >> 8) & 0xff);
+/*       emitcode ("subb", "a,#!constbyte", */
+/*                 -((sym->stack < 0) ? */
+/*                   ((short) (sym->stack - _G.nRegsSaved)) : */
+/*                   ((short) sym->stack)) & 0xff); */
+/*       emitcode ("mov","b,a"); */
+/*       emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
+/*                                      ((short) (sym->stack - _G.nRegsSaved)) : */
+/*                                      ((short) sym->stack)) >> 8) & 0xff); */
          if (sym->stack) {
              emitcode ("mov", "a,_bpx");
              emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
@@ -10092,16 +10454,16 @@ genAddrOf (iCode * ic)
       if (offset) {
          switch (offset) {
          case 1:
-             tsprintf(s,"!his",sym->rname);
+             tsprintf(s, sizeof(s), "!his",sym->rname);
              break;
          case 2:
-             tsprintf(s,"!hihis",sym->rname);
+             tsprintf(s, sizeof(s), "!hihis",sym->rname);
              break;
          case 3:
-             tsprintf(s,"!hihihis",sym->rname);
+             tsprintf(s, sizeof(s), "!hihihis",sym->rname);
              break;
          default: /* should not need this (just in case) */
-             sprintf (s, "#(%s >> %d)",
+             SNPRINTF (s, sizeof(s), "#(%s >> %d)",
                       sym->rname,
                       offset * 8);
          }
@@ -10562,8 +10924,6 @@ genCast (iCode * ic)
       /* pointer to generic pointer */
       if (IS_GENPTR (ctype))
        {
-         char *l = zero;
-
          if (IS_PTR (type))
            {
              p_type = DCL_TYPE (type);
@@ -10623,29 +10983,19 @@ genCast (iCode * ic)
          _endLazyDPSEvaluation ();
 
          /* the last byte depending on type */
-         switch (p_type)
            {
-           case IPOINTER:
-           case POINTER:
-             l = zero;
-             break;
-           case FPOINTER:
-             l = one;
-             break;
-           case CPOINTER:
-             l = "#0x02";
-             break;
-           case PPOINTER:
-             l = "#0x03";
-             break;
-
-           default:
-             /* this should never happen */
-             werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-                     "got unknown pointer type");
-             exit (1);
+               int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
+               char gpValStr[10];
+           
+               if (gpVal == -1)
+               {
+                   // pointerTypeToGPByte will have bitched.
+                   exit(1);
+               }
+           
+               sprintf(gpValStr, "#0x%d", gpVal);
+               aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
            }
-         aopPut (AOP (result), l, GPTRSIZE - 1);
          goto release;
        }
 
@@ -10801,39 +11151,51 @@ static void
 genReceive (iCode * ic)
 {
 
-  D (emitcode (";", "genReceive ");
-    );
-
-  if (isOperandInFarSpace (IC_RESULT (ic)) &&
-      (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
-       IS_TRUE_SYMOP (IC_RESULT (ic))))
-    {
-      int size = getSize (operandType (IC_RESULT (ic)));
-      int offset = fReturnSizeDS390 - size;
-      while (size--)
-       {
-         emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
-                           fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
-         offset++;
-       }
-      aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
-      size = AOP_SIZE (IC_RESULT (ic));
-      offset = 0;
-      while (size--)
-       {
-         emitcode ("pop", "acc");
-         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
-       }
+    int size = getSize (operandType (IC_RESULT (ic)));
+    int offset = 0;
+    int rb1off ;
+    
+    D (emitcode (";", "genReceive ");
+       );
 
-    }
-  else
-    {
-      _G.accInUse++;
+  if (ic->argreg == 1) { /* first parameter */
+      if (isOperandInFarSpace (IC_RESULT (ic)) &&
+         (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
+          IS_TRUE_SYMOP (IC_RESULT (ic))))
+         {
+             offset = fReturnSizeDS390 - size;
+             while (size--)
+                 {
+                     emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
+                                              fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
+                     offset++;
+                 }
+             aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+             size = AOP_SIZE (IC_RESULT (ic));
+             offset = 0;
+             while (size--)
+                 {
+                     emitcode ("pop", "acc");
+                     aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+                 }
+             
+         } else {
+             _G.accInUse++;
+             aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+             _G.accInUse--;
+             assignResultValue (IC_RESULT (ic));
+         }
+  } else { /* second receive onwards */
+      /* this gets a little tricky since unused recevies will be
+        eliminated, we have saved the reg in the type field . and
+        we use that to figure out which register to use */
       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
-      _G.accInUse--;
-      assignResultValue (IC_RESULT (ic));
-    }
-
+      rb1off = ic->argreg;
+      while (size--) {
+         aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
+      }
+      
+  }
   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
@@ -10903,16 +11265,28 @@ static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
        }
     }
     freeAsmop (to, NULL, ic, FALSE);
-
+    _G.dptrInUse = _G.dptr1InUse = 1;
     aopOp (count, ic->next->next, FALSE,FALSE);
     lbl =newiTempLabel(NULL);
 
     /* now for the actual copy */
     if (AOP_TYPE(count) == AOP_LIT && 
        (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
-       emitcode (";","OH  JOY auto increment with djnz (very fast)");
-       emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
        emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
+       if (fromc) {
+           emitcode ("lcall","__bi_memcpyc2x_s");
+       } else {
+           emitcode ("lcall","__bi_memcpyx2x_s");
+       }
+       freeAsmop (count, NULL, ic, FALSE);
+    } else {
+       symbol *lbl1 = newiTempLabel(NULL);
+       
+       emitcode (";"," Auto increment but no djnz");
+       emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
+       emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
+       freeAsmop (count, NULL, ic, FALSE);
+       emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
        emitcode ("","!tlabeldef",lbl->key+100);
        if (fromc) {
            emitcode ("clr","a");
@@ -10922,13 +11296,115 @@ static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
        emitcode ("movx", "@dptr,a");
        emitcode ("inc", "dptr");
        emitcode ("inc", "dptr");
-       emitcode ("djnz","b,!tlabel",lbl->key+100);
+       emitcode ("mov","a,b");
+       emitcode ("orl","a,_ap");
+       emitcode ("jz","!tlabel",lbl1->key+100);
+       emitcode ("mov","a,_ap");
+       emitcode ("add","a,#!constbyte",0xFF);
+       emitcode ("mov","_ap,a");
+       emitcode ("mov","a,b");
+       emitcode ("addc","a,#!constbyte",0xFF);
+       emitcode ("mov","b,a");
+       emitcode ("sjmp","!tlabel",lbl->key+100);
+       emitcode ("","!tlabeldef",lbl1->key+100);
+    }
+    emitcode ("mov", "dps,#0"); 
+    _G.dptrInUse = _G.dptr1InUse = 0;
+    unsavermask(rsave);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genMemcmpX2X - gen code for memcmp xdata to xdata               */
+/*-----------------------------------------------------------------*/
+static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
+{
+    operand *from , *to , *count;
+    symbol *lbl,*lbl2;
+    bitVect *rsave;
+    int i;
+
+    /* we know it has to be 3 parameters */
+    assert (nparms == 3);
+    
+    rsave = newBitVect(16);
+    /* save DPTR if it needs to be saved */
+    for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
+           if (bitVectBitValue(ic->rMask,i))
+                   rsave = bitVectSetBit(rsave,i);
+    }
+    rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
+                                                 ds390_rUmaskForOp (IC_RESULT(ic))));
+    savermask(rsave);
+    
+    to = parms[0];
+    from = parms[1];
+    count = parms[2];
+
+    aopOp (from, ic->next, FALSE, FALSE);
+
+    /* get from into DPTR1 */
+    emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
+    emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
+    if (options.model == MODEL_FLAT24) {
+       emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
+    }
+
+    freeAsmop (from, NULL, ic, FALSE);
+    aopOp (to, ic, FALSE, FALSE);
+    /* get "to" into DPTR */
+    /* if the operand is already in dptr
+       then we do nothing else we move the value to dptr */
+    if (AOP_TYPE (to) != AOP_STR) {
+       /* if already in DPTR then we need to push */
+       if (AOP_TYPE(to) == AOP_DPTR) {
+           emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
+           emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
+           if (options.model == MODEL_FLAT24)
+               emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
+           emitcode ("pop", "dph");
+           emitcode ("pop", "dpl");        
+       } else {
+           _startLazyDPSEvaluation ();
+           /* if this is remateriazable */
+           if (AOP_TYPE (to) == AOP_IMMD) {
+               emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
+           } else {                    /* we need to get it byte by byte */
+               emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
+               emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
+               if (options.model == MODEL_FLAT24) {
+                   emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
+               }
+           }
+           _endLazyDPSEvaluation ();
+       }
+    }
+    freeAsmop (to, NULL, ic, FALSE);
+    _G.dptrInUse = _G.dptr1InUse = 1;
+    aopOp (count, ic->next->next, FALSE,FALSE);
+    lbl =newiTempLabel(NULL);
+    lbl2 =newiTempLabel(NULL);
+
+    /* now for the actual compare */
+    if (AOP_TYPE(count) == AOP_LIT && 
+       (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
+       emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
+       if (fromc)
+           emitcode("lcall","__bi_memcmpc2x_s");
+       else
+           emitcode("lcall","__bi_memcmpx2x_s");
+       freeAsmop (count, NULL, ic, FALSE);
+       aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
+       aopPut(AOP(IC_RESULT(ic)),"a",0);
+       freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
     } else {
        symbol *lbl1 = newiTempLabel(NULL);
-       
+
+       emitcode("push","ar0");         
        emitcode (";"," Auto increment but no djnz");
        emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
        emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
+       freeAsmop (count, NULL, ic, FALSE);
        emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
        emitcode ("","!tlabeldef",lbl->key+100);
        if (fromc) {
@@ -10936,9 +11412,259 @@ static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
            emitcode ("movc", "a,@a+dptr");
        } else 
            emitcode ("movx", "a,@dptr");
+       emitcode ("mov","r0,a");
+       emitcode ("movx", "a,@dptr");
+       emitcode ("clr","c");
+       emitcode ("subb","a,r0");
+       emitcode ("jnz","!tlabel",lbl2->key+100);
+       emitcode ("inc", "dptr");
+       emitcode ("inc", "dptr");
+       emitcode ("mov","a,b");
+       emitcode ("orl","a,_ap");
+       emitcode ("jz","!tlabel",lbl1->key+100);
+       emitcode ("mov","a,_ap");
+       emitcode ("add","a,#!constbyte",0xFF);
+       emitcode ("mov","_ap,a");
+       emitcode ("mov","a,b");
+       emitcode ("addc","a,#!constbyte",0xFF);
+       emitcode ("mov","b,a");
+       emitcode ("sjmp","!tlabel",lbl->key+100);
+       emitcode ("","!tlabeldef",lbl1->key+100);
+       emitcode ("clr","a");
+       emitcode ("","!tlabeldef",lbl2->key+100);
+       aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
+       aopPut(AOP(IC_RESULT(ic)),"a",0);
+       freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
+       emitcode("pop","ar0");
+       emitcode ("mov", "dps,#0");      
+    }
+    _G.dptrInUse = _G.dptr1InUse = 0;
+    unsavermask(rsave);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genInp - gen code for __builtin_inp read data from a mem mapped */
+/* port, first parameter output area second parameter pointer to   */
+/* port third parameter count                                      */
+/*-----------------------------------------------------------------*/
+static void genInp( iCode *ic, int nparms, operand **parms)
+{
+    operand *from , *to , *count;
+    symbol *lbl;
+    bitVect *rsave;
+    int i;
+
+    /* we know it has to be 3 parameters */
+    assert (nparms == 3);
+    
+    rsave = newBitVect(16);
+    /* save DPTR if it needs to be saved */
+    for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
+           if (bitVectBitValue(ic->rMask,i))
+                   rsave = bitVectSetBit(rsave,i);
+    }
+    rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
+                                                 ds390_rUmaskForOp (IC_RESULT(ic))));
+    savermask(rsave);
+    
+    to = parms[0];
+    from = parms[1];
+    count = parms[2];
+
+    aopOp (from, ic->next, FALSE, FALSE);
+
+    /* get from into DPTR1 */
+    emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
+    emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
+    if (options.model == MODEL_FLAT24) {
+       emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
+    }
+
+    freeAsmop (from, NULL, ic, FALSE);
+    aopOp (to, ic, FALSE, FALSE);
+    /* get "to" into DPTR */
+    /* if the operand is already in dptr
+       then we do nothing else we move the value to dptr */
+    if (AOP_TYPE (to) != AOP_STR) {
+       /* if already in DPTR then we need to push */
+       if (AOP_TYPE(to) == AOP_DPTR) {
+           emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
+           emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
+           if (options.model == MODEL_FLAT24)
+               emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
+           emitcode ("pop", "dph");
+           emitcode ("pop", "dpl");        
+       } else {
+           _startLazyDPSEvaluation ();
+           /* if this is remateriazable */
+           if (AOP_TYPE (to) == AOP_IMMD) {
+               emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
+           } else {                    /* we need to get it byte by byte */
+               emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
+               emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
+               if (options.model == MODEL_FLAT24) {
+                   emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
+               }
+           }
+           _endLazyDPSEvaluation ();
+       }
+    }
+    freeAsmop (to, NULL, ic, FALSE);
+
+    _G.dptrInUse = _G.dptr1InUse = 1;
+    aopOp (count, ic->next->next, FALSE,FALSE);
+    lbl =newiTempLabel(NULL);
+
+    /* now for the actual copy */
+    if (AOP_TYPE(count) == AOP_LIT && 
+       (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
+       emitcode (";","OH  JOY auto increment with djnz (very fast)");
+       emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
+       emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
+       freeAsmop (count, NULL, ic, FALSE);
+       emitcode ("","!tlabeldef",lbl->key+100);
+       emitcode ("movx", "a,@dptr");   /* read data from port */
+       emitcode ("dec","dps");         /* switch to DPTR */
+       emitcode ("movx", "@dptr,a");   /* save into location */
+       emitcode ("inc", "dptr");       /* point to next area */
+       emitcode ("inc","dps");         /* switch to DPTR2 */
+       emitcode ("djnz","b,!tlabel",lbl->key+100);
+    } else {
+       symbol *lbl1 = newiTempLabel(NULL);
+       
+       emitcode (";"," Auto increment but no djnz");
+       emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
+       emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
+       freeAsmop (count, NULL, ic, FALSE);
+       emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
+       emitcode ("","!tlabeldef",lbl->key+100);
+       emitcode ("movx", "a,@dptr");
+       emitcode ("dec","dps");         /* switch to DPTR */
        emitcode ("movx", "@dptr,a");
        emitcode ("inc", "dptr");
+       emitcode ("inc","dps");         /* switch to DPTR2 */
+/*     emitcode ("djnz","b,!tlabel",lbl->key+100); */
+/*     emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
+       emitcode ("mov","a,b");
+       emitcode ("orl","a,_ap");
+       emitcode ("jz","!tlabel",lbl1->key+100);
+       emitcode ("mov","a,_ap");
+       emitcode ("add","a,#!constbyte",0xFF);
+       emitcode ("mov","_ap,a");
+       emitcode ("mov","a,b");
+       emitcode ("addc","a,#!constbyte",0xFF);
+       emitcode ("mov","b,a");
+       emitcode ("sjmp","!tlabel",lbl->key+100);
+       emitcode ("","!tlabeldef",lbl1->key+100);
+    }
+    emitcode ("mov", "dps,#0"); 
+    _G.dptrInUse = _G.dptr1InUse = 0;
+    unsavermask(rsave);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genOutp - gen code for __builtin_inp write data to a mem mapped */
+/* port, first parameter output area second parameter pointer to   */
+/* port third parameter count                                      */
+/*-----------------------------------------------------------------*/
+static void genOutp( iCode *ic, int nparms, operand **parms)
+{
+    operand *from , *to , *count;
+    symbol *lbl;
+    bitVect *rsave;
+    int i;
+
+    /* we know it has to be 3 parameters */
+    assert (nparms == 3);
+    
+    rsave = newBitVect(16);
+    /* save DPTR if it needs to be saved */
+    for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
+           if (bitVectBitValue(ic->rMask,i))
+                   rsave = bitVectSetBit(rsave,i);
+    }
+    rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
+                                                 ds390_rUmaskForOp (IC_RESULT(ic))));
+    savermask(rsave);
+    
+    to = parms[0];
+    from = parms[1];
+    count = parms[2];
+
+    aopOp (from, ic->next, FALSE, FALSE);
+
+    /* get from into DPTR1 */
+    emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
+    emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
+    if (options.model == MODEL_FLAT24) {
+       emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
+    }
+
+    freeAsmop (from, NULL, ic, FALSE);
+    aopOp (to, ic, FALSE, FALSE);
+    /* get "to" into DPTR */
+    /* if the operand is already in dptr
+       then we do nothing else we move the value to dptr */
+    if (AOP_TYPE (to) != AOP_STR) {
+       /* if already in DPTR then we need to push */
+       if (AOP_TYPE(to) == AOP_DPTR) {
+           emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
+           emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
+           if (options.model == MODEL_FLAT24)
+               emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
+           emitcode ("pop", "dph");
+           emitcode ("pop", "dpl");        
+       } else {
+           _startLazyDPSEvaluation ();
+           /* if this is remateriazable */
+           if (AOP_TYPE (to) == AOP_IMMD) {
+               emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
+           } else {                    /* we need to get it byte by byte */
+               emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
+               emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
+               if (options.model == MODEL_FLAT24) {
+                   emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
+               }
+           }
+           _endLazyDPSEvaluation ();
+       }
+    }
+    freeAsmop (to, NULL, ic, FALSE);
+
+    _G.dptrInUse = _G.dptr1InUse = 1;
+    aopOp (count, ic->next->next, FALSE,FALSE);
+    lbl =newiTempLabel(NULL);
+
+    /* now for the actual copy */
+    if (AOP_TYPE(count) == AOP_LIT && 
+       (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
+       emitcode (";","OH  JOY auto increment with djnz (very fast)");
+       emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
+       emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
+       emitcode ("","!tlabeldef",lbl->key+100);
+       emitcode ("movx", "a,@dptr");   /* read data from port */
+       emitcode ("inc","dps");         /* switch to DPTR2 */
+       emitcode ("movx", "@dptr,a");   /* save into location */
+       emitcode ("inc", "dptr");       /* point to next area */
+       emitcode ("dec","dps");         /* switch to DPTR */
+       emitcode ("djnz","b,!tlabel",lbl->key+100);
+       freeAsmop (count, NULL, ic, FALSE);
+    } else {
+       symbol *lbl1 = newiTempLabel(NULL);
+       
+       emitcode (";"," Auto increment but no djnz");
+       emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
+       emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
+       freeAsmop (count, NULL, ic, FALSE);
+       emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
+       emitcode ("","!tlabeldef",lbl->key+100);
+       emitcode ("movx", "a,@dptr");
        emitcode ("inc", "dptr");
+       emitcode ("inc","dps");         /* switch to DPTR2 */
+       emitcode ("movx", "@dptr,a");
+       emitcode ("dec","dps");         /* switch to DPTR */
        emitcode ("mov","a,b");
        emitcode ("orl","a,_ap");
        emitcode ("jz","!tlabel",lbl1->key+100);
@@ -10952,11 +11678,38 @@ static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
        emitcode ("","!tlabeldef",lbl1->key+100);
     }
     emitcode ("mov", "dps,#0"); 
-    freeAsmop (count, NULL, ic, FALSE);
+    _G.dptrInUse = _G.dptr1InUse = 0;
     unsavermask(rsave);
 
 }
 
+/*-----------------------------------------------------------------*/
+/* genSwapW - swap lower & high order bytes                        */
+/*-----------------------------------------------------------------*/
+static void genSwapW(iCode *ic, int nparms, operand **parms)
+{
+    operand *dest;
+    operand *src;
+    assert (nparms==1);
+
+    src = parms[0];
+    dest=IC_RESULT(ic);
+
+    assert(getSize(operandType(src))==2);
+
+    aopOp (src, ic, FALSE, FALSE);
+    emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
+    _G.accInUse++;
+    emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
+    _G.accInUse--;
+    freeAsmop (src, NULL, ic, FALSE);
+    
+    aopOp (dest,ic, FALSE, FALSE);
+    aopPut(AOP(dest),"b",0);
+    aopPut(AOP(dest),"a",1);
+    freeAsmop (dest, NULL, ic, FALSE);    
+}
+
 /*-----------------------------------------------------------------*/
 /* genMemsetX - gencode for memSetX data                           */
 /*-----------------------------------------------------------------*/
@@ -11036,7 +11789,7 @@ static void genMemsetX(iCode *ic, int nparms, operand **parms)
        emitcode ("","!tlabeldef",lbl->key+100);
        l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
        MOVA(l);
-       emitcode ("movx", "a,@dptr");
+       emitcode ("movx", "@dptr,a");
        emitcode ("inc", "dptr");
        emitcode ("mov","a,b");
        emitcode ("orl","a,_ap");
@@ -11671,8 +12424,19 @@ static void genBuiltIn (iCode *ic)
                genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
        } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
                genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
+       } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
+               genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
+       } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
+               genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
        } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
                genMemsetX(bi_iCode,nbi_parms,bi_parms);
+       } else if (strcmp(bif->name,"__builtin_inp")==0) {
+               genInp(bi_iCode,nbi_parms,bi_parms);
+       } else if (strcmp(bif->name,"__builtin_outp")==0) {
+               genOutp(bi_iCode,nbi_parms,bi_parms);
+       } else if (strcmp(bif->name,"__builtin_swapw")==0) {
+               genSwapW(bi_iCode,nbi_parms,bi_parms);
+               /* JavaNative builtIns */               
        } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
                genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
        } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
@@ -11760,7 +12524,10 @@ gen390Code (iCode * lic)
   int cln = 0;
 
   lineHead = lineCurr = NULL;
-
+  dptrn[1][0] = "dpl1";
+  dptrn[1][1] = "dph1";
+  dptrn[1][2] = "dpx1";
+  
   if (options.model == MODEL_FLAT24) {
     fReturnSizeDS390 = 5;
     fReturn = fReturn24;
@@ -11769,8 +12536,7 @@ gen390Code (iCode * lic)
     fReturn = fReturn16;
     options.stack10bit=0;
   }
-#if 0
-  //REMOVE ME!!!
+#if 1
   /* print the allocation information */
   if (allocInfo)
     printAllocInfo (currFunc, codeOutFile);
@@ -11796,7 +12562,7 @@ gen390Code (iCode * lic)
   for (ic = lic; ic; ic = ic->next)
     {
 
-      if (cln != ic->lineno)
+      if (ic->lineno && cln != ic->lineno)
        {
          if (options.debug)
            {
@@ -11806,9 +12572,15 @@ gen390Code (iCode * lic)
                        ic->level, ic->block);
              _G.debugLine = 0;
            }
-         emitcode (";", "%s %d", ic->filename, ic->lineno);
+         if (!options.noCcodeInAsm) {
+           emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
+                     printCLine(ic->filename, ic->lineno));
+         }
          cln = ic->lineno;
        }
+      if (options.iCodeInAsm) {
+       emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
+      }
       /* if the result is marked as
          spilt and rematerializable or code for
          this has already been generated then
@@ -11966,12 +12738,12 @@ gen390Code (iCode * lic)
          break;
 
        case GET_VALUE_AT_ADDRESS:
-         genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
+         genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
          break;
 
        case '=':
          if (POINTER_SET (ic))
-           genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
+           genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
          else
            genAssign (ic);
          break;