]> git.gag.com Git - fw/sdcc/commitdiff
1) handle multiple send & receives from register bank1
authorsandeep <sandeep@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 30 Jan 2002 04:40:09 +0000 (04:40 +0000)
committersandeep <sandeep@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 30 Jan 2002 04:40:09 +0000 (04:40 +0000)
2) ralloc can now allocate DPTR1 to some liveRanges

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1870 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/ds390/gen.c
src/ds390/gen.h
src/ds390/ralloc.c

index c215d327b1f9b7936b4a2ea83359a9c732eadf3e..1aa6a2fe9f401337467462bd97e9bb3c3b51e569 100644 (file)
@@ -80,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;
 
@@ -96,6 +97,10 @@ static struct
   }
 _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) \
@@ -131,6 +136,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    */
@@ -467,7 +486,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
       /* It's on the 10 bit stack, which is located in
        * far data space.
        */
-       if (stack_val < 0 && stack_val > -3) { /* between -3 & -1 */
+       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);
@@ -551,7 +570,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));
@@ -612,8 +631,12 @@ 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);
@@ -853,7 +876,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);
@@ -862,7 +885,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 */
@@ -1052,6 +1081,10 @@ aopGet (asmop * aop,
       strcpy (rs, s);
       return rs;
 
+    case AOP_DPTRn:
+       assert(offset <= 3);
+       return dptrn[aop->aopu.dptr][offset];
+
     case AOP_DPTR:
     case AOP_DPTR2:
 
@@ -1228,6 +1261,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:
 
@@ -1435,6 +1472,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.
@@ -2300,6 +2339,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                            */
 /*-----------------------------------------------------------------*/
@@ -2343,36 +2432,10 @@ genCall (iCode * ic)
   */
   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, 
-                  (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);
+       if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
+           genSend(reverseSet(_G.sendSet));
+       } else {
+           genSend(_G.sendSet);
        }
       _G.sendSet = NULL;
     }  
@@ -2439,19 +2502,22 @@ genCall (iCode * ic)
   if (ic->parmBytes) {
       int i;
       if (options.stack10bit) {
-         if (ic->parmBytes <= 4) {
+         if (ic->parmBytes <= 10) {
              emitcode(";","stack adjustment for parms");
              for (i=0; i < ic->parmBytes ; i++) {
                  emitcode("pop","acc");
              }
-         } else {
+         } 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) {
@@ -2524,37 +2590,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", "");
@@ -2582,18 +2619,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);
@@ -2710,8 +2765,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"))
@@ -2740,13 +2794,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)
@@ -2767,6 +2821,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
@@ -2919,14 +2978,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);
@@ -2973,8 +3039,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);
       }
@@ -3019,10 +3087,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
@@ -3030,12 +3098,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)
@@ -3055,6 +3123,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);
            }
        }
@@ -3441,6 +3514,15 @@ genPlusIncr (iCode * ic)
       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)
@@ -3560,24 +3642,6 @@ 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
-
 // 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
@@ -4051,7 +4115,8 @@ 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))
     {
@@ -4092,40 +4157,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);
@@ -5983,6 +6050,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;
            }
        }
@@ -9017,7 +9088,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)
@@ -9052,42 +9123,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);
@@ -9108,7 +9207,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)
@@ -9142,41 +9241,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);
@@ -9761,7 +9890,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)
@@ -9794,47 +9923,76 @@ 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 (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);
-      pi->generated=1;
-  } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
-            (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
-      
-      size = AOP_SIZE (right) - 1;
-      while (size--) emitcode ("lcall","__decdptr");
-  }
-  freeAsmop (result, NULL, ic, TRUE);
-  freeAsmop (right, NULL, ic, TRUE);
-}
+      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) {
+      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_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);
+}
 
 /*-----------------------------------------------------------------*/
 /* genGenPointerSet - set value from generic pointer space         */
@@ -10820,39 +10978,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);
 }
 
@@ -10976,6 +11146,409 @@ static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
 
 }
 
+/*-----------------------------------------------------------------*/
+/* 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);
+
+    aopOp (count, ic->next->next, FALSE,FALSE);
+    lbl =newiTempLabel(NULL);
+    lbl2 =newiTempLabel(NULL);
+
+    /* now for the actual compare */
+    emitcode("push","ar0");
+    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));
+       emitcode ("","!tlabeldef",lbl->key+100);
+       if (fromc) {
+           emitcode ("clr","a");
+           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 ("djnz","b,!tlabel",lbl->key+100);
+       emitcode ("clr","a");   
+    } 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));
+       emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
+       emitcode ("","!tlabeldef",lbl->key+100);
+       if (fromc) {
+           emitcode ("clr","a");
+           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");
+    }
+    freeAsmop (count, NULL, ic, FALSE);
+    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"); 
+    
+    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);
+
+    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));
+       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));
+       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"); 
+    freeAsmop (count, NULL, ic, FALSE);
+    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);
+
+    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);
+    } 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));
+       emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
+       emitcode ("","!tlabeldef",lbl->key+100);
+/*     emitcode ("push","acc"); */
+       emitcode ("movx", "a,@dptr");
+       emitcode ("inc", "dptr");
+       emitcode ("inc","dps");         /* switch to DPTR2 */
+       emitcode ("movx", "@dptr,a");
+       emitcode ("dec","dps");         /* switch to DPTR */
+/*     emitcode ("pop","acc"); */
+/*     emitcode ("djnz","acc,!tlabel",lbl->key+100); */
+/*     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"); 
+    freeAsmop (count, NULL, ic, FALSE);
+    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                           */
 /*-----------------------------------------------------------------*/
@@ -11055,7 +11628,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");
@@ -11690,8 +12263,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) {
@@ -11779,7 +12363,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;
index d238ca9b24eeafdf1e318f4c58e75add3e15aae9..04726f8b2ecda116d4580fdba852eb09bb08b99f 100644 (file)
@@ -31,7 +31,7 @@ enum
     AOP_REG, AOP_DIR,
     AOP_DPTR, AOP_DPTR2, AOP_R0, AOP_R1,
     AOP_STK, AOP_IMMD, AOP_STR,
-    AOP_CRY, AOP_ACC
+    AOP_CRY, AOP_ACC, AOP_DPTRn
   };
 
 /* type asmop : a homogenised type for 
@@ -53,6 +53,7 @@ typedef struct asmop
                                   AOP_CRY    -  carry contains the value of this
                                   AOP_STR    -  array of strings
                                   AOP_ACC    -  result is in the acc:b pair
+                                  AOP_DPTRn  -  is in dptr(n)
                                 */
     short coff;                        /* current offset */
     short size;                        /* total size */
@@ -61,6 +62,7 @@ typedef struct asmop
     unsigned freed:1;          /* already freed    */
     union
       {
+       short dptr;             /* if AOP_DPTRn */
        value *aop_lit;         /* if literal */
        regs *aop_reg[4];       /* array of registers */
        char *aop_dir;          /* if direct  */
index d731417dbf76deb8ffa770e67a6310d8825db95a..dd1a2ab60b3ada130c9f11b60018296c565bfa50 100644 (file)
@@ -83,6 +83,7 @@ int ds390_nRegs = 13;
 static void spillThis (symbol *);
 static void freeAllRegs ();
 static iCode * packRegsDPTRuse (operand *);
+static int packRegsDPTRnuse (operand *,int);
 
 /*-----------------------------------------------------------------*/
 /* allocReg - allocates register of given type                     */
@@ -221,7 +222,9 @@ allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
 static int isOperandInReg(operand *op)
 {
     if (!IS_SYMOP(op)) return 0;
-
+    if (OP_SYMBOL(op)->ruonly) return 1;
+    if (OP_SYMBOL(op)->accuse) return 1;
+    if (OP_SYMBOL(op)->dptr) return 1;
     return bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(op)->key);
 }
 
@@ -308,7 +311,8 @@ static int
 notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic)
 {
   return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) &&
-         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq) &&
+         allDefsOutOfRange (sym->uses, ebp->fSeq, ebp->lSeq));
 /*     return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
 }
 
@@ -1150,7 +1154,9 @@ serialRegAssign (eBBlock ** ebbs, int count)
          (ebbs[i]->entryLabel != entryLabel &&
           ebbs[i]->entryLabel != returnLabel))
        continue;
-
+      
+/*       if (returnsAtEnd(ebbs[i])) */
+      
       /* of all instructions do */
       for (ic = ebbs[i]->sch; ic; ic = ic->next)
        {
@@ -1298,131 +1304,159 @@ static void fillGaps()
 {
     symbol *sym =NULL;
     int key =0;    
-    
+    int loop = 0, change;
+
     if (getenv("DISABLE_FILL_GAPS")) return;
     
     /* First try to do DPTRuse once more since now we know what got into
-       registers */
-
-    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
-        sym = hTabNextItem(liveRanges,&key)) {
-
-       if (sym->uptr && !sym->ruonly && getSize(sym->type) < 4) {
-           if (packRegsDPTRuse(operandFromSymbol(sym))) {
-
-                D (fprintf (stderr, "FILL GAPS: found more DPTR use for "
-                           "%s in func %s\n",
-                           sym->name, currFunc ? currFunc->name : "UNKNOWN"));
-               /* if this was ssigned to registers then */
-               if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
-
-                   /* take it out of the register assigned set */
-                   bitVectUnSetBit(_G.totRegAssigned,sym->key);
+       registers */ 
+    
+    while (loop++ < 10) {
+       change = 0;
+
+       for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+            sym = hTabNextItem(liveRanges,&key)) {
+           int size = getSize(sym->type);
+
+           if (sym->liveFrom == sym->liveTo) continue;
+
+           if (sym->uptr && sym->dptr==0 && !sym->ruonly && 
+               size < 4 && size > 1) {
+
+               if (packRegsDPTRuse(operandFromSymbol(sym))) {
+                   
+                   /* if this was ssigned to registers then */
+                   if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+                       /* take it out of the register assigned set */
+                       bitVectUnSetBit(_G.totRegAssigned,sym->key);
+                   } else if (sym->usl.spillLoc) {
+                       sym->usl.spillLoc->allocreq--;
+                       sym->usl.spillLoc = NULL;
+                   }
+                   
                    sym->nRegs = 0;                 
-               } else if (sym->usl.spillLoc) sym->usl.spillLoc->allocreq--;
+                   sym->isspilt = sym->spillA = 0;
+                   continue ;
+               }
 
-               sym->isspilt = sym->spillA = 0;
+               /* try assigning other dptrs */
+               if (sym->dptr == 0 && packRegsDPTRnuse(operandFromSymbol(sym),1) && !getenv("DPTRnDISABLE")) {
+                   /* if this was ssigned to registers then */
+                   if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+                       /* take it out of the register assigned set */
+                       bitVectUnSetBit(_G.totRegAssigned,sym->key);
+                   } else if (sym->usl.spillLoc) {
+                       sym->usl.spillLoc->allocreq--;
+                       sym->usl.spillLoc = NULL;
+                   }
+/*                 printf("Allocated %s in function %s to DPTR1\n",sym->name,currFunc->name); */
+                   sym->nRegs = 0;                 
+                   sym->isspilt = sym->spillA = 0;                 
+               }
            }
        }
-    }
-
-    /* look for livernages that was spilt by the allocator */
-    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
-        sym = hTabNextItem(liveRanges,&key)) {
-
-       int i;
-       int pdone = 0;
-
-       if (!sym->spillA || !sym->clashes || sym->remat) continue ;
-
-       /* find the liveRanges this one clashes with, that are
-          still assigned to registers & mark the registers as used*/
-       for ( i = 0 ; i < sym->clashes->size ; i ++) {
-           int k;
-           symbol *clr;
-
-           if (bitVectBitValue(sym->clashes,i) == 0 ||    /* those that clash with this */
-               bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+       
+       /* look for livernages that was spilt by the allocator */
+       for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+            sym = hTabNextItem(liveRanges,&key)) {
+           
+           int i;
+           int pdone = 0;
+           
+           if (!sym->spillA || !sym->clashes || sym->remat) continue ;
+           if (!sym->uses || !sym->defs) continue ;
+           /* find the liveRanges this one clashes with, that are
+              still assigned to registers & mark the registers as used*/
+           for ( i = 0 ; i < sym->clashes->size ; i ++) {
+               int k;
+               symbol *clr;
+               
+               if (bitVectBitValue(sym->clashes,i) == 0 ||    /* those that clash with this */
+                   bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+                   continue ;
+               
+               assert (clr = hTabItemWithKey(liveRanges,i));
+               
+               /* mark these registers as used */
+               for (k = 0 ; k < clr->nRegs ; k++ ) 
+                   useReg(clr->regs[k]);
+           }
+           
+           if (willCauseSpill(sym->nRegs,sym->regType)) {
+               /* NOPE :( clear all registers & and continue */
+               freeAllRegs();
                continue ;
-
-           assert (clr = hTabItemWithKey(liveRanges,i));
-        
-           /* mark these registers as used */
-           for (k = 0 ; k < clr->nRegs ; k++ ) 
-               useReg(clr->regs[k]);
-       }
-
-       if (willCauseSpill(sym->nRegs,sym->regType)) {
-           /* NOPE :( clear all registers & and continue */
-           freeAllRegs();
-           continue ;
-       }
-
-       /* THERE IS HOPE !!!! */
-       for (i=0; i < sym->nRegs ; i++ ) {
-           if (sym->regType == REG_PTR)
-               sym->regs[i] = getRegPtrNoSpil ();
-           else
-               sym->regs[i] = getRegGprNoSpil ();                
-       }
-
-       /* for all its definitions & uses check if the registers
-          allocated needs positioning NOTE: we can position
-          only ONCE if more than One positioning required 
-          then give up */
-       sym->isspilt = 0;
-       for (i = 0 ; i < sym->defs->size ; i++ ) {
-           if (bitVectBitValue(sym->defs,i)) {
-               iCode *ic;
-               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
-               if (SKIP_IC(ic)) continue;
-               assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */
-               /* if left is assigned to registers */
-               if (IS_SYMOP(IC_LEFT(ic)) && 
-                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) {
-                   pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)));
-               }
-               if (IS_SYMOP(IC_RIGHT(ic)) && 
-                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
-                   pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
+           }
+           
+           /* THERE IS HOPE !!!! */
+           for (i=0; i < sym->nRegs ; i++ ) {
+               if (sym->regType == REG_PTR)
+                   sym->regs[i] = getRegPtrNoSpil ();
+               else
+                   sym->regs[i] = getRegGprNoSpil ();            
+           }
+           
+           /* for all its definitions & uses check if the registers
+              allocated needs positioning NOTE: we can position
+              only ONCE if more than One positioning required 
+              then give up */
+           sym->isspilt = 0;
+           for (i = 0 ; i < sym->defs->size ; i++ ) {
+               if (bitVectBitValue(sym->defs,i)) {
+                   iCode *ic;
+                   if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+                   if (SKIP_IC(ic)) continue;
+                   assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */
+                   /* if left is assigned to registers */
+                   if (IS_SYMOP(IC_LEFT(ic)) && 
+                       bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) {
+                       pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)));
+                   }
+                   if (IS_SYMOP(IC_RIGHT(ic)) && 
+                       bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+                       pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
+                   }
+                   if (pdone > 1) break;
                }
-               if (pdone > 1) break;
            }
-       }
-               for (i = 0 ; i < sym->uses->size ; i++ ) {
-           if (bitVectBitValue(sym->uses,i)) {
-               iCode *ic;
-               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
-               if (SKIP_IC(ic)) continue;
-               if (!IS_ASSIGN_ICODE(ic)) continue ;
-
-               /* if result is assigned to registers */
-               if (IS_SYMOP(IC_RESULT(ic)) && 
-                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
-                   pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
+           for (i = 0 ; i < sym->uses->size ; i++ ) {
+               if (bitVectBitValue(sym->uses,i)) {
+                   iCode *ic;
+                   if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+                   if (SKIP_IC(ic)) continue;
+                   if (!IS_ASSIGN_ICODE(ic)) continue ;
+                   
+                   /* if result is assigned to registers */
+                   if (IS_SYMOP(IC_RESULT(ic)) && 
+                       bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
+                       pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
+                   }
+                   if (pdone > 1) break;
                }
-               if (pdone > 1) break;
            }
-       }
-       /* had to position more than once GIVE UP */
-       if (pdone > 1) {
-           /* UNDO all the changes we made to try this */
-           sym->isspilt = 1;
-           for (i=0; i < sym->nRegs ; i++ ) {
-               sym->regs[i] = NULL;
+           /* had to position more than once GIVE UP */
+           if (pdone > 1) {
+               /* UNDO all the changes we made to try this */
+               sym->isspilt = 1;
+               for (i=0; i < sym->nRegs ; i++ ) {
+                   sym->regs[i] = NULL;
+               }
+               freeAllRegs();
+               D (fprintf (stderr, "Fill Gap gave up due to positioning for "
+                           "%s in function %s\n",
+                           sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+               continue ;          
            }
-           freeAllRegs();
-           D (fprintf (stderr, "Fill Gap gave up due to positioning for "
-                       "%s in function %s\n",
+           D (fprintf (stderr, "FILLED GAP for %s in function %s\n",
                        sym->name, currFunc ? currFunc->name : "UNKNOWN"));
-           continue ;      
+           _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
+           sym->isspilt = sym->spillA = 0 ;
+           sym->usl.spillLoc->allocreq--;
+           sym->usl.spillLoc = NULL;
+           freeAllRegs();
+           change ++;
        }
-       D (fprintf (stderr, "FILLED GAP for %s in function %s\n",
-                   sym->name, currFunc ? currFunc->name : "UNKNOWN"));
-       _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
-       sym->isspilt = sym->spillA = 0 ;
-       sym->usl.spillLoc->allocreq--;
-       freeAllRegs();
+       if (!change) break;
     }
 }
 
@@ -1917,6 +1951,7 @@ pack:
   /* replace the result with the result of */
   /* this assignment and remove this assignment */
   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+
   IC_RESULT (dic) = IC_RESULT (ic);
 
   if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
@@ -2098,6 +2133,103 @@ right:
 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
 
 
+/*-----------------------------------------------------------------*/
+/* packRegsDPTRnuse - color live ranges that can go into extra DPTRS */
+/*-----------------------------------------------------------------*/
+static int packRegsDPTRnuse( operand *op , int dptr)
+{
+    int i,key;
+    iCode *ic;
+
+    if (!IS_SYMOP(op) || !IS_ITEMP(op)) return 0;
+    if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly || OP_SYMBOL(op)->dptr) 
+       return 0; 
+    
+    /* first check if any overlapping liverange has already been
+       assigned to this DPTR */
+    if (OP_SYMBOL(op)->clashes) {
+       for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) {
+           symbol *sym;
+           if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) {
+               sym = hTabItemWithKey(liveRanges,i);
+               if (sym->dptr == dptr) return 0;
+           }
+       }
+    }
+   
+    /* future for more dptrs */
+    if (dptr > 1) {
+       OP_SYMBOL(op)->dptr = dptr;
+       return 1;
+    }
+
+    /* DPTR1 is special since it is also used as a scratch by the backend .
+       so we walk thru the entire live range of this operand and make sure
+       DPTR1 will not be used by the backed . The logic here is to find out if 
+       more than one operand in an icode is in far space then we give up : we 
+       don't keep it live across functions for now
+    */
+    
+    ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+    for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+        ic = hTabNextItem(iCodeSeqhTab,&key)) {
+       int nfs =0;
+       
+       if (ic->op == CALL || ic->op == PCALL) return 0;
+
+       /* single operand icode are ok */
+       if (ic->op == IFX || ic->op == IPUSH)
+           continue ;
+
+       if (ic->op == SEND ) {
+           if (ic->argreg != 1) return 0;
+           else continue ;
+       }
+       /* two special cases first */
+       if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op)  && /* pointer get */
+           !OP_SYMBOL(IC_LEFT(ic))->ruonly                     && /* with result in far space */
+           (isOperandInFarSpace(IC_RESULT(ic)) &&              
+            !isOperandInReg(IC_RESULT(ic)))) {
+           return 0;
+       }
+
+       if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op)        && /* pointer set */
+           !OP_SYMBOL(IC_RESULT(ic))->ruonly                           && /* with right in far space */
+           (isOperandInFarSpace(IC_RIGHT(ic)) &&               
+            !isOperandInReg(IC_RIGHT(ic)))) {
+           return 0;
+       }
+
+       if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))    && /* if symbol operand */
+           !isOperandEqual(IC_RESULT(ic),op)           && /* not the same as this */
+           ((isOperandInFarSpace(IC_RESULT(ic)) ||        /* in farspace or */
+             OP_SYMBOL(IC_RESULT(ic))->onStack)        && /* on the stack   */
+            !isOperandInReg(IC_RESULT(ic)))) {            /* and not in register */
+           nfs++;
+       }
+       /* same for left */
+       if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic))        && /* if symbol operand */
+           !isOperandEqual(IC_LEFT(ic),op)             && /* not the same as this */
+           ((isOperandInFarSpace(IC_LEFT(ic)) ||          /* in farspace or */
+             OP_SYMBOL(IC_LEFT(ic))->onStack)          && /* on the stack   */
+            !isOperandInReg(IC_LEFT(ic)))) {              /* and not in register */
+           nfs++;
+       }
+       /* same for right */
+       if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic))      && /* if symbol operand */
+           !isOperandEqual(IC_RIGHT(ic),op)            && /* not the same as this */
+           ((isOperandInFarSpace(IC_RIGHT(ic)) ||         /* in farspace or */
+             OP_SYMBOL(IC_RIGHT(ic))->onStack)         && /* on the stack   */
+            !isOperandInReg(IC_RIGHT(ic)))) {             /* and not in register */
+           nfs++;
+       }
+       
+       if (nfs > 1) return 0;
+    }
+    OP_SYMBOL(op)->dptr = dptr;
+    return 1;
+}
+
 /*-----------------------------------------------------------------*/
 /* packRegsDPTRuse : - will reduce some registers for single Use */
 /*-----------------------------------------------------------------*/
@@ -2137,6 +2269,9 @@ packRegsDPTRuse (operand * op)
        /* if PCALL cannot be sure give up */
        if (ic->op == PCALL) return NULL;
 
+       /* if SEND & not the first parameter then giveup */
+       if (ic->op == SEND && ic->argreg != 1) return NULL;
+
        /* if CALL then make sure it is VOID || return value not used 
           or the return value is assigned to this one */
        if (ic->op == CALL) {
@@ -2171,7 +2306,8 @@ packRegsDPTRuse (operand * op)
 
        /* if this is a cast to a bigger type */
        if (ic->op==CAST) {
-         if (getSize(OP_SYM_TYPE(IC_RESULT(ic))) >
+         if (!IS_PTR(OP_SYM_TYPE(IC_RESULT(ic))) && 
+             getSize(OP_SYM_TYPE(IC_RESULT(ic))) >
              getSize(OP_SYM_TYPE(IC_RIGHT(ic)))) {
            return 0;
          }
@@ -2180,25 +2316,25 @@ packRegsDPTRuse (operand * op)
        /* general case */
        if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && 
            !isOperandEqual(IC_RESULT(ic),op) &&
-           ((isOperandInFarSpace(IC_RESULT(ic)) && !isOperandInReg(IC_RESULT(ic))) || 
-            OP_SYMBOL(IC_RESULT(ic))->ruonly   ||
-            OP_SYMBOL(IC_RESULT(ic))->onStack)) return NULL;
+           ( ( ( isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->onStack) && 
+               !isOperandInReg(IC_RESULT(ic))) || 
+            OP_SYMBOL(IC_RESULT(ic))->ruonly)) return NULL;
 
        if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && 
            !isOperandEqual(IC_RIGHT(ic),op) &&
            (OP_SYMBOL(IC_RIGHT(ic))->liveTo >= ic->seq || 
             IS_TRUE_SYMOP(IC_RIGHT(ic))               ||
             OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
-           ((isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic)))|| 
-            OP_SYMBOL(IC_RIGHT(ic))->onStack)) return NULL;
+           ( ( isOperandInFarSpace(IC_RIGHT(ic)) || OP_SYMBOL(IC_RIGHT(ic))->onStack) && 
+               !isOperandInReg(IC_RIGHT(ic))) ) return NULL;
 
        if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && 
            !isOperandEqual(IC_LEFT(ic),op) &&
            (OP_SYMBOL(IC_LEFT(ic))->liveTo > ic->seq || 
             IS_TRUE_SYMOP(IC_LEFT(ic))               ||
             OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
-           ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic)))|| 
-            OP_SYMBOL(IC_LEFT(ic))->onStack)) return NULL;
+           ( ( isOperandInFarSpace(IC_LEFT(ic)) || OP_SYMBOL(IC_LEFT(ic))->onStack) && 
+               !isOperandInReg(IC_LEFT(ic))) ) return NULL;
        
        if (IC_LEFT(ic) && IC_RIGHT(ic) && 
            IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) &&
@@ -2338,14 +2474,8 @@ packRegsForAccUse (iCode * ic)
 
   /* make sure that the result of this icode is not on the
      stack, since acc is used to compute stack offset */
-#if 0
-  if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
-      OP_SYMBOL (IC_RESULT (uic))->onStack)
-    return;
-#else
   if (isOperandOnStack(IC_RESULT(uic)))
     return;
-#endif
 
   /* if either one of them in far space then we cannot */
   if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
@@ -2365,19 +2495,6 @@ packRegsForAccUse (iCode * ic)
       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
     return;
 
-#if 0
-  // this is too dangerous and need further restrictions
-  // see bug #447547
-
-  /* if one of them is a literal then we can */
-  if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
-      (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))
-    {
-      OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
-      return;
-    }
-#endif
-
   /* if the other one is not on stack then we can */
   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
       (IS_ITEMP (IC_RIGHT (uic)) ||
@@ -2408,7 +2525,7 @@ packForPush (iCode * ic, eBBlock * ebp)
   iCode *dic, *lic;
   bitVect *dbv;
 
-  if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+  if ((ic->op != IPUSH && ic->op != SEND) || !IS_ITEMP (IC_LEFT (ic)))
     return;
 
   /* must have only definition & one usage */
@@ -2443,6 +2560,12 @@ packForPush (iCode * ic, eBBlock * ebp)
   if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
          OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
   }
+  for (lic = ic; lic && lic != dic; lic = lic->prev)
+    {
+      bitVectUnSetBit (lic->rlive, IC_LEFT (ic)->key);
+      if (IS_ITEMP (IC_RIGHT (dic)))
+       bitVectSetBit (lic->rlive, IC_RIGHT (dic)->key);
+    }
   /* we now we know that it has one & only one def & use
      and the that the definition is an assignment */
   IC_LEFT (ic) = IC_RIGHT (dic);
@@ -2502,6 +2625,18 @@ packRegisters (eBBlock * ebp)
 
        }
 
+       /* if this is an itemp & used as a pointer
+          & assigned to a literal then remat */
+       if (IS_ASSIGN_ICODE(ic) && 
+           IS_ITEMP(IC_RESULT(ic)) &&
+           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+           isOperandLiteral(IC_RIGHT(ic))) 
+       {
+         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;          
+       }
+
       /* if straight assignment then carry remat flag if
          this is the only definition */
       if (ic->op == '=' &&
@@ -2522,6 +2657,7 @@ packRegisters (eBBlock * ebp)
         cast is remat, then we can remat this cast as well */
       if (ic->op == CAST && 
          IS_SYMOP(IC_RIGHT(ic)) &&
+         !OP_SYMBOL(IC_RESULT(ic))->isreqv &&
          OP_SYMBOL(IC_RIGHT(ic))->remat ) {
              sym_link *to_type = operandType(IC_LEFT(ic));
              sym_link *from_type = operandType(IC_RIGHT(ic));
@@ -2559,6 +2695,10 @@ packRegisters (eBBlock * ebp)
       if (ic->op == RETURN && IS_SYMOP (IC_LEFT(ic)))
          OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
 
+      if (ic->op == RECEIVE && ic->argreg == 1 &&
+         getSize (operandType(IC_RESULT(ic))) <= 3)
+         OP_SYMBOL (IC_RESULT(ic))->uptr = 1;
+
       if (!SKIP_IC2 (ic))
        {
          /* if we are using a symbol on the stack
@@ -2583,21 +2723,6 @@ packRegisters (eBBlock * ebp)
            }
        }
 
-#if 0
-      /* if the condition of an if instruction
-         is defined in the previous instruction then
-         mark the itemp as a conditional */
-      if ((IS_CONDITIONAL (ic) ||
-          (IS_BITWISE_OP(ic) && isBitwiseOptimizable(ic))) &&
-         ic->next && ic->next->op == IFX &&
-         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
-         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
-       {
-
-         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
-         continue;
-       }
-#else
       /* if the condition of an if instruction
          is defined in the previous instruction and
         this is the only usage then
@@ -2612,15 +2737,15 @@ packRegisters (eBBlock * ebp)
          OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
          continue;
        }
-#endif
-
+#if 1
       /* reduce for support function calls */
       if (ic->supportRtn || ic->op == '+' || ic->op == '-')
        packRegsForSupport (ic, ebp);
-
+#endif
       /* some cases the redundant moves can
-         can be eliminated for return statements */
-      if ((ic->op == RETURN || ic->op == SEND) &&        
+         can be eliminated for return statements . Can be elminated for the first SEND */      
+      if ((ic->op == RETURN || 
+          ((ic->op == SEND || ic->op == RECEIVE)&& ic->argreg == 1)) &&          
          !isOperandInFarSpace (IC_LEFT (ic)) &&
          !options.model) {
         
@@ -2717,7 +2842,7 @@ packRegisters (eBBlock * ebp)
          -------------
          push V1
        */
-      if (ic->op == IPUSH)
+      if (ic->op == IPUSH || ic->op == SEND)
        {
          packForPush (ic, ebp);
        }
@@ -2734,7 +2859,7 @@ packRegisters (eBBlock * ebp)
       if ((IS_ARITHMETIC_OP (ic)
           || IS_CONDITIONAL(ic)
           || IS_BITWISE_OP (ic)
-          || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL
+          || ic->op == LEFT_OP || ic->op == RIGHT_OP 
           || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
          ) &&
          IS_ITEMP (IC_RESULT (ic)) &&