work in progress: several improvements to generated code
[fw/sdcc] / src / ds390 / gen.c
index 73a4f0bdc5a77d037ac90eddae9cd25b4b9777fd..7ece8206e67934d1a946e32a752ecb6963797c1a 100644 (file)
@@ -226,7 +226,7 @@ endOfWorld :
     /* other wise this is true end of the world */
     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
            "getFreePtr should never reach here");
-    exit(0);
+    exit(1);
 }
 
 /*-----------------------------------------------------------------*/
@@ -241,8 +241,31 @@ static asmop *newAsmop (short type)
     return aop;
 }
 
+/* #define LAZY_DPS_OPT */ /* turn this on after some more testing. */
+
+static int _currentDPS;          /* Current processor DPS. */
+static int _desiredDPS;          /* DPS value compiler thinks we should be using. */
+static int _lazyDPS = 0;  /* if non-zero, we are doing lazy evaluation of DPS changes. */
+
+/*-----------------------------------------------------------------*/
+/* genSetDPTR: generate code to select which DPTR is in use (zero  */
+/* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390            */
+/* alternate DPTR (DPL1/DPH1/DPX1).                               */
+/*-----------------------------------------------------------------*/
 static void genSetDPTR(int n)
 {
+
+#ifdef LAZY_DPS_OPT
+    /* If we are doing lazy evaluation, simply note the desired
+     * change, but don't emit any code yet.
+     */
+    if (_lazyDPS)
+    {
+        _desiredDPS = n;
+        return;
+    }
+#endif
+
     if (!n)
     {
         emitcode("mov", "dps, #0x00");
@@ -253,6 +276,76 @@ static void genSetDPTR(int n)
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
+/*                                                                */
+/* Any code that operates on DPTR (NB: not on the individual      */
+/* components, like DPH) *must* call _flushLazyDPS() before using  */
+/* DPTR within a lazy DPS evaluation block.                       */
+/*                                                                */
+/* Note that aopPut and aopGet already contain the proper calls to */
+/* _flushLazyDPS, so it is safe to use these calls within a lazy   */
+/* DPS evaluation block.                                          */
+/*                                                                */
+/* Also, _flushLazyDPS must be called before any flow control     */
+/* operations that could potentially branch out of the block.     */
+/*                                                                */
+/* Lazy DPS evaluation is simply an optimization (though an       */
+/* important one), so if in doubt, leave it out.                  */
+/*-----------------------------------------------------------------*/
+static void _startLazyDPSEvaluation(void)
+{
+   _currentDPS = 0;
+   _desiredDPS = 0;
+   _lazyDPS = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* _flushLazyDPS: emit code to force the actual DPS setting to the */
+/* desired one. Call before using DPTR within a lazy DPS evaluation*/
+/* block.                                                         */
+/*-----------------------------------------------------------------*/
+static void _flushLazyDPS(void)
+{
+    if (!_lazyDPS)
+    {
+        /* nothing to do. */
+        return;
+    }
+    
+    if (_desiredDPS != _currentDPS)
+    {
+       if (_desiredDPS)
+       {
+           emitcode("inc", "dps");
+       }
+       else
+       {
+           emitcode("dec", "dps");
+       }
+       _currentDPS = _desiredDPS;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* _endLazyDPSEvaluation: end lazy DPS evaluation block.          */
+/*                                                                */
+/* Forces us back to the safe state (standard DPTR selected).     */
+/*-----------------------------------------------------------------*/
+static void _endLazyDPSEvaluation(void)
+{
+   if (_currentDPS)
+   {
+       genSetDPTR(0);
+       _flushLazyDPS();
+   }
+   _lazyDPS = 0;
+   _currentDPS = 0;
+   _desiredDPS = 0;
+}
+
+
+
 /*-----------------------------------------------------------------*/
 /* pointerCode - returns the code for a pointer type               */
 /*-----------------------------------------------------------------*/
@@ -328,11 +421,11 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
         
        if (useDP2)
        {        
-        genSetDPTR(1);
+        /* genSetDPTR(1); */
         emitcode ("mov","dpx1,#0x40");
         emitcode ("mov","dph1,#0x00");
         emitcode ("mov","dpl1, a");
-        genSetDPTR(0);
+        /* genSetDPTR(0); */
         }
         else
         {
@@ -379,7 +472,8 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
     if (useDP2)
     {        
         genSetDPTR(1);
-    emitcode ("mov","dptr,#%s", sym->rname);
+        _flushLazyDPS();
+       emitcode ("mov","dptr,#%s", sym->rname);
         genSetDPTR(0);
     }    
     else
@@ -793,17 +887,19 @@ static char *aopGet (asmop *aop,
     case AOP_DPTR:
     case AOP_DPTR2:
     
-    if (aop->type == AOP_DPTR2)
-    {
-        genSetDPTR(1);
+       if (aop->type == AOP_DPTR2)
+       {
+            genSetDPTR(1);
         
 #ifndef KEVIN_BROKE_IT        
-        if (!canClobberACC)
+            if (!canClobberACC)
 #endif        
-        {
-            emitcode("xch", "a, ap");
-        }
-    }
+            {
+               emitcode("xch", "a, ap");
+            }
+       }
+    
+       _flushLazyDPS();
     
        while (offset > aop->coff) {
            emitcode ("inc","dptr");
@@ -820,25 +916,24 @@ static char *aopGet (asmop *aop,
            emitcode("clr","a");
            emitcode("movc","a,@a+dptr");
         }
-    else {
+       else {
            emitcode("movx","a,@dptr");
-    }
+       }
            
-    if (aop->type == AOP_DPTR2)
-    {
-       genSetDPTR(0);
+       if (aop->type == AOP_DPTR2)
+       {
+           genSetDPTR(0);
 
 #ifndef KEVIN_BROKE_IT        
-        if (!canClobberACC)
+            if (!canClobberACC)
 #endif        
-        {
-            emitcode("xch", "a, ap");
-            return "ap";
-        }
-    }
+            {
+               emitcode("xch", "a, ap");
+               return "ap";
+            }
+       }
            
-    return (dname ? "acc" : "a");
-       
+       return (dname ? "acc" : "a");
        
     case AOP_IMMD:
        if (bit16) 
@@ -898,7 +993,7 @@ static char *aopGet (asmop *aop,
 
     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
            "aopget got unsupported aop->type");
-    exit(0);
+    exit(1);
 }
 /*-----------------------------------------------------------------*/
 /* aopPut - puts a string for a aop                                */
@@ -911,7 +1006,7 @@ static void aopPut (asmop *aop, char *s, int offset)
     if (aop->size && offset > ( aop->size - 1)) {
         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
                "aopPut got offset > aop->size");
-        exit(0);
+        exit(1);
     }
 
     /* will assign value to value */
@@ -952,15 +1047,16 @@ static void aopPut (asmop *aop, char *s, int offset)
     case AOP_DPTR:
     case AOP_DPTR2:
     
-    if (aop->type == AOP_DPTR2)
-    {
-        genSetDPTR(1);
-    }
+       if (aop->type == AOP_DPTR2)
+       {
+            genSetDPTR(1);
+       }
+       _flushLazyDPS();
     
        if (aop->code) {
            werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
                   "aopPut writting to code space");
-           exit(0);
+           exit(1);
        }
        
        while (offset > aop->coff) {
@@ -980,10 +1076,10 @@ static void aopPut (asmop *aop, char *s, int offset)
        
        emitcode ("movx","@dptr,a");
        
-    if (aop->type == AOP_DPTR2)
-    {
-        genSetDPTR(0);
-    }
+       if (aop->type == AOP_DPTR2)
+       {
+            genSetDPTR(0);
+       }
        break;
        
     case AOP_R0:
@@ -1079,7 +1175,7 @@ static void aopPut (asmop *aop, char *s, int offset)
     default :
        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
               "aopPut got unsupported aop->type");
-       exit(0);    
+       exit(1);    
     }    
 
 }
@@ -1133,6 +1229,7 @@ static void reAdjustPreg (asmop *aop)
             if (aop->type == AOP_DPTR2)
            {
                 genSetDPTR(1);
+                _flushLazyDPS();
            } 
             while (size--)
             {
@@ -1207,6 +1304,7 @@ static void genNotFloat (operand *op, operand *res)
     size = AOP_SIZE(op) - 1;
     offset = 1;
 
+    _startLazyDPSEvaluation();
     l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
     MOVA(l);    
 
@@ -1215,6 +1313,7 @@ static void genNotFloat (operand *op, operand *res)
                  aopGet(op->aop,
                         offset++,FALSE,FALSE,FALSE));
     }
+    _endLazyDPSEvaluation();
     tlbl = newiTempLabel(NULL);
 
     tlbl = newiTempLabel(NULL);
@@ -1307,6 +1406,18 @@ static void toBoolean(operand *oper)
     int size = AOP_SIZE(oper) - 1;
     int offset = 1;
 
+    /* The generic part of a generic pointer should
+     * not participate in it's truth value.
+     *
+     * i.e. 0x10000000 is zero.
+     */
+    if (opIsGptr(oper))
+    {
+       D(emitcode(";", "toBoolean: generic ptr special case."););
+               size--;
+    }
+
+    _startLazyDPSEvaluation();
     if (AOP_NEEDSACC(oper))
     {
         emitcode("push", "b");
@@ -1324,9 +1435,10 @@ static void toBoolean(operand *oper)
        }
        else
        {
-        emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
-}
+            emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
+       }
     }
+    _endLazyDPSEvaluation();
     
     if (AOP_NEEDSACC(oper))
     {
@@ -1405,12 +1517,14 @@ static void genCpl (iCode *ic)
     } 
 
     size = AOP_SIZE(IC_RESULT(ic));
+    _startLazyDPSEvaluation();
     while (size--) {
         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
         MOVA(l);       
         emitcode("cpl","a");
         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
     }
+    _endLazyDPSEvaluation();
 
 
 release:
@@ -1430,6 +1544,7 @@ static void genUminusFloat(operand *op,operand *result)
     first it then copy the rest in place */
     D(emitcode(";", "genUminusFloat"););
     
+    _startLazyDPSEvaluation();
     size = AOP_SIZE(op) - 1;
     l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
     MOVA(l);    
@@ -1442,7 +1557,8 @@ static void genUminusFloat(operand *op,operand *result)
                aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
                offset);
         offset++;
-    }          
+    }
+    _endLazyDPSEvaluation();
 }
 
 /*-----------------------------------------------------------------*/
@@ -1484,6 +1600,7 @@ static void genUminus (iCode *ic)
     size = AOP_SIZE(IC_LEFT(ic));
     offset = 0 ;
     //CLRC ;
+    _startLazyDPSEvaluation();
     while(size--) {
         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
         if (!strcmp(l,"a")) {
@@ -1499,6 +1616,7 @@ static void genUminus (iCode *ic)
         }       
         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
     }
+    _endLazyDPSEvaluation();
 
     /* if any remaining bytes in the result */
     /* we just need to propagate the sign   */
@@ -1621,6 +1739,7 @@ static void unsaveRegisters (iCode *ic)
 static void pushSide(operand * oper, int size)
 {
        int offset = 0;
+       _startLazyDPSEvaluation();
        while (size--) {
                char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
                if (AOP_TYPE(oper) != AOP_REG &&
@@ -1631,6 +1750,7 @@ static void pushSide(operand * oper, int size)
                } else
                        emitcode("push","%s",l);
        }
+       _endLazyDPSEvaluation();
 }
 
 /*-----------------------------------------------------------------*/
@@ -1640,10 +1760,13 @@ static void assignResultValue(operand * oper)
 {
        int offset = 0;
        int size = AOP_SIZE(oper);
+       
+       _startLazyDPSEvaluation();
        while (size--) {
                aopPut(AOP(oper),fReturn[offset],offset);
                offset++;
        }
+       _endLazyDPSEvaluation();
 }
 
 
@@ -1665,6 +1788,7 @@ static void genXpush (iCode *ic)
     emitcode("mov","%s,_spx",r->name);
 
     size = AOP_SIZE(IC_LEFT(ic));
+    _startLazyDPSEvaluation();
     while(size--) {
 
        char *l = aopGet(AOP(IC_LEFT(ic)),
@@ -1674,6 +1798,7 @@ static void genXpush (iCode *ic)
        emitcode("inc","%s",r->name);
 
     }
+    _endLazyDPSEvaluation();
 
        
     emitcode("mov","_spx,%s",r->name);
@@ -1704,6 +1829,7 @@ static void genIpush (iCode *ic)
         aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
         size = AOP_SIZE(IC_LEFT(ic));
         /* push it on the stack */
+        _startLazyDPSEvaluation();
         while(size--) {
             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
             if (*l == '#') {
@@ -1712,6 +1838,7 @@ static void genIpush (iCode *ic)
             }
             emitcode("push","%s",l);
         }
+        _endLazyDPSEvaluation();
         return ;        
     }
 
@@ -1734,6 +1861,7 @@ static void genIpush (iCode *ic)
        // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
     size = AOP_SIZE(IC_LEFT(ic));
 
+    _startLazyDPSEvaluation();
     while (size--) {
         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
@@ -1743,7 +1871,8 @@ static void genIpush (iCode *ic)
             emitcode("push","acc");
         } else
             emitcode("push","%s",l);
-    }       
+    }
+    _endLazyDPSEvaluation();
 
     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
 }
@@ -1765,9 +1894,13 @@ static void genIpop (iCode *ic)
     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
     size = AOP_SIZE(IC_LEFT(ic));
     offset = (size-1);
-    while (size--) 
+    _startLazyDPSEvaluation();
+    while (size--)
+    {
         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
                                    FALSE,TRUE,TRUE));
+    }
+    _endLazyDPSEvaluation();
 
     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
 }
@@ -1890,19 +2023,24 @@ static void genCall (iCode *ic)
        iCode *sic ;
 
        for (sic = setFirstItem(_G.sendSet) ; sic ; 
-            sic = setNextItem(_G.sendSet)) {
+            sic = setNextItem(_G.sendSet)) 
+       {
            int size, offset = 0;
-        aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
+        
+            aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
            size = AOP_SIZE(IC_LEFT(sic));
+           
+           _startLazyDPSEvaluation();
            while (size--) {
                char *l = aopGet(AOP(IC_LEFT(sic)),offset,
-                               FALSE, FALSE, FALSE);
+                               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;
@@ -1918,16 +2056,29 @@ static void genCall (iCode *ic)
           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
 
+#ifdef LAZY_DPS_OPT
+       /* Not really related to LAZY_DPS_OPT, but don't want
+        * another testing flag right now...
+        */
+        _G.accInUse++;
+        aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
+        _G.accInUse--;
+                                     
+        assignResultValue(IC_RESULT(ic));
+                                                  
+        freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
+                                                                      
+#else
        if (!isOperandInFarSpace(IC_RESULT(ic)))
        {
-        _G.accInUse++;
+            _G.accInUse++;
             aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
-        _G.accInUse--;
+            _G.accInUse--;
 
-       assignResultValue(IC_RESULT(ic));
+           assignResultValue(IC_RESULT(ic));
                
-        freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
-    }
+            freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
+       }
         else
         {
             /* Result is in far space, and requires DPTR to access
@@ -1960,7 +2111,8 @@ static void genCall (iCode *ic)
                aopPut(AOP(IC_RESULT(ic)),"a",++offset);
            }
            freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
-        }
+       }
+#endif 
     }
 
     /* adjust the stack for parameters if 
@@ -2037,22 +2189,29 @@ static void genPcall (iCode *ic)
        iCode *sic ;
 
        for (sic = setFirstItem(_G.sendSet) ; sic ; 
-            sic = setNextItem(_G.sendSet)) {
-           int size, offset = 0;
-           aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
-           size = AOP_SIZE(IC_LEFT(sic));
-           while (size--) {
-               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
-                               FALSE,FALSE,FALSE);
-               if (strcmp(l,fReturn[offset]))
-                   emitcode("mov","%s,%s",
-                            fReturn[offset],
-                            l);
-               offset++;
+            sic = setNextItem(_G.sendSet)) 
+            {
+               int size, offset = 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 (strcmp(l,fReturn[offset]))
+                       {
+                               emitcode("mov","%s,%s",
+                                        fReturn[offset],
+                                        l);
+                       }
+                       offset++;
+               }
+               _endLazyDPSEvaluation();
+               freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
            }
-           freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
-       }
-       _G.sendSet = NULL;
+           _G.sendSet = NULL;
     }
 
     emitcode("ret","");
@@ -2479,6 +2638,7 @@ static void genRet (iCode *ic)
     aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
     size = AOP_SIZE(IC_LEFT(ic));
     
+    _startLazyDPSEvaluation();
     while (size--) {
            char *l ;
            if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
@@ -2492,7 +2652,8 @@ static void genRet (iCode *ic)
                    if (strcmp(fReturn[offset],l))
                            emitcode("mov","%s,%s",fReturn[offset++],l);
            }
-    }    
+    }
+    _endLazyDPSEvaluation();    
 
     if (pushed) {
        while(pushed) {
@@ -2679,8 +2840,12 @@ static bool genPlusIncr (iCode *ic)
             aopPut(AOP(IC_RESULT(ic)),"a",0);
         } else {
            
+           _startLazyDPSEvaluation();
             while (icount--) 
+            {
                 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
+            }
+            _endLazyDPSEvaluation();
         }
        
         return TRUE ;
@@ -2786,6 +2951,7 @@ static void genPlus (iCode *ic)
 {
     int size, offset = 0;
     bool pushResult = FALSE;
+    int  rSize;
 
     D(emitcode(";", "genPlus "););
 
@@ -2832,11 +2998,13 @@ static void genPlus (iCode *ic)
             outBitC(IC_RESULT(ic));
         } else {
             size = getDataSize(IC_RESULT(ic));
+            _startLazyDPSEvaluation();
             while (size--) {
                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
                 emitcode("addc","a,#00");
                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
             }
+            _endLazyDPSEvaluation();
         }
         goto release ;
     }
@@ -2849,8 +3017,11 @@ static void genPlus (iCode *ic)
     }
     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
 
-    while(size--){
-       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+    _startLazyDPSEvaluation();
+    while(size--)
+    {
+       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) 
+       {
            MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
            if(offset == 0)
                emitcode("add","a,%s",
@@ -2877,12 +3048,40 @@ static void genPlus (iCode *ic)
         }
         offset++;
     }
-
+    _endLazyDPSEvaluation();
+   
     if (pushResult)
     {
         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
 
         size = getDataSize(IC_LEFT(ic));
+       rSize = getDataSize(IC_RESULT(ic));
+       
+       /* If the pushed data is bigger than the result,
+        * simply discard unused bytes. Icky, but works.
+        *
+        * Should we throw a warning here? We're losing data...
+        */
+       while (size > rSize)
+       {
+          D(emitcode(";", "discarding unused result byte."););
+          emitcode("pop", "acc");
+          size--;
+          offset--; 
+       }
+       if (size < rSize)
+       {
+           emitcode("clr", "a");
+           /* Conversly, we haven't pushed enough here.
+            * just zero-pad, and all is well. 
+            */
+           while (size < rSize)
+           {
+               emitcode("push", "acc");
+               size++;
+               offset++;
+           }
+       }
 
         while(size--)
         {
@@ -3010,8 +3209,12 @@ static bool genMinusDec (iCode *ic)
         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
 
+       _startLazyDPSEvaluation();
         while (icount--) 
+        {
             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
+        }
+        _endLazyDPSEvaluation();
 
         return TRUE ;
     }
@@ -3070,6 +3273,7 @@ static void genMinusBits (iCode *ic)
 static void genMinus (iCode *ic)
 {
     int size, offset = 0;
+    int rSize;
     unsigned long lit = 0L;
     bool pushResult = FALSE;
 
@@ -3113,6 +3317,7 @@ static void genMinus (iCode *ic)
 
 
     /* if literal, add a,#-lit, else normal subb */
+    _startLazyDPSEvaluation();
     while (size--) {
         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
@@ -3138,12 +3343,40 @@ static void genMinus (iCode *ic)
         }
         offset++;
     }
+    _endLazyDPSEvaluation();
 
     if (pushResult)
     {
         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
 
         size = getDataSize(IC_LEFT(ic));
+        rSize = getDataSize(IC_RESULT(ic));
+
+       /* If the pushed data is bigger than the result,
+        * simply discard unused bytes. Icky, but works.
+        *
+        * Should we throw a warning here? We're losing data...
+        */
+       while (size > getDataSize(IC_RESULT(ic)))
+       {
+          emitcode(";", "discarding unused result byte.");
+          emitcode("pop", "acc");
+          size--;
+          offset--; 
+       }
+       if (size < rSize)
+       {
+           emitcode("clr", "a");
+           /* Conversly, we haven't pushed enough here.
+            * just zero-pad, and all is well. 
+            */
+           while (size < rSize)
+           {
+               emitcode("push", "acc");
+               size++;
+               offset++;
+           }
+       }
 
         while(size--)
         {
@@ -3641,7 +3874,7 @@ static void genCmp (operand *left,operand *right,
         {
             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
                    "both CMP operands need ACC!");
-            exit(-1);
+            exit(1);
         }
         else
         {
@@ -3863,8 +4096,19 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
         right = left;
         left = t;
     }
+    
     if(AOP_TYPE(right) == AOP_LIT)
         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+        
+    if (opIsGptr(left) || opIsGptr(right))
+    {
+        /* We are comparing a generic pointer to something.
+         * Exclude the generic type byte from the comparison.
+         */
+        size--;
+        D(emitcode(";", "cjneshort: generic ptr special case.");) 
+    }
+         
 
     /* if the right side is a literal then anything goes */
     if (AOP_TYPE(right) == AOP_LIT &&
@@ -3884,8 +4128,10 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
     else if (AOP_TYPE(right) == AOP_REG ||
              AOP_TYPE(right) == AOP_DIR || 
              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
-             (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
-        while (size--) {
+             (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) 
+    {
+        while (size--) 
+        {
             MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
@@ -4971,6 +5217,8 @@ static void genRRC (iCode *ic)
     size = AOP_SIZE(result);    
     offset = size - 1 ;
     CLRC;
+    
+    _startLazyDPSEvaluation();
     while (size--) {
         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
         MOVA(l);
@@ -4978,6 +5226,8 @@ static void genRRC (iCode *ic)
         if (AOP_SIZE(result) > 1)
             aopPut(AOP(result),"a",offset--);
     }
+    _endLazyDPSEvaluation();
+    
     /* now we need to put the carry into the
     highest order byte of the result */
     if (AOP_SIZE(result) > 1) {
@@ -5015,7 +5265,11 @@ static void genRLC (iCode *ic)
         MOVA(l);
         emitcode("add","a,acc");
         if (AOP_SIZE(result) > 1)
+        {
             aopPut(AOP(result),"a",offset++);
+        }
+            
+        _startLazyDPSEvaluation();
         while (size--) {
             l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
             MOVA(l);
@@ -5023,6 +5277,7 @@ static void genRLC (iCode *ic)
             if (AOP_SIZE(result) > 1)
                 aopPut(AOP(result),"a",offset++);
         }
+        _endLazyDPSEvaluation();
     }
     /* now we need to put the carry into the
     highest order byte of the result */
@@ -5800,6 +6055,7 @@ static void genLeftShift (iCode *ic)
 
         size = AOP_SIZE(result);
         offset=0;
+        _startLazyDPSEvaluation();
         while (size--) {
             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
             if (*l == '@' && (IS_AOP_PREG(result))) {
@@ -5810,6 +6066,7 @@ static void genLeftShift (iCode *ic)
                 aopPut(AOP(result),l,offset);
             offset++;
         }
+        _endLazyDPSEvaluation();
     }
 
     tlbl = newiTempLabel(NULL);
@@ -5840,12 +6097,14 @@ static void genLeftShift (iCode *ic)
     MOVA(l);
     emitcode("add","a,acc");         
     aopPut(AOP(result),"a",offset++);
+    _startLazyDPSEvaluation();
     while (--size) {
         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
         MOVA(l);
         emitcode("rlc","a");         
         aopPut(AOP(result),"a",offset++);
     }
+    _endLazyDPSEvaluation();
     reAdjustPreg(AOP(result));
 
     emitcode("","%05d$:",tlbl1->key+100);
@@ -6088,6 +6347,7 @@ static void genSignedRightShift (iCode *ic)
 
         size = AOP_SIZE(result);
         offset=0;
+        _startLazyDPSEvaluation();
         while (size--) {
             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
             if (*l == '@' && IS_AOP_PREG(result)) {
@@ -6098,6 +6358,7 @@ static void genSignedRightShift (iCode *ic)
                 aopPut(AOP(result),l,offset);
             offset++;
         }
+        _endLazyDPSEvaluation();
     }
 
     /* mov the highest order bit to OVR */    
@@ -6127,12 +6388,14 @@ static void genSignedRightShift (iCode *ic)
     emitcode("sjmp","%05d$",tlbl1->key+100);
     emitcode("","%05d$:",tlbl->key+100);    
     emitcode("mov","c,ov");
+    _startLazyDPSEvaluation();
     while (size--) {
         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
         MOVA(l);
         emitcode("rrc","a");         
         aopPut(AOP(result),"a",offset--);
     }
+    _endLazyDPSEvaluation();
     reAdjustPreg(AOP(result));
     emitcode("","%05d$:",tlbl1->key+100);
     emitcode("djnz","b,%05d$",tlbl->key+100);
@@ -6205,6 +6468,7 @@ static void genRightShift (iCode *ic)
 
         size = AOP_SIZE(result);
         offset=0;
+        _startLazyDPSEvaluation();
         while (size--) {
             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
             if (*l == '@' && IS_AOP_PREG(result)) {
@@ -6215,6 +6479,7 @@ static void genRightShift (iCode *ic)
                 aopPut(AOP(result),l,offset);
             offset++;
         }
+        _endLazyDPSEvaluation();
     }
 
     tlbl = newiTempLabel(NULL);
@@ -6240,12 +6505,14 @@ static void genRightShift (iCode *ic)
     emitcode("sjmp","%05d$",tlbl1->key+100);
     emitcode("","%05d$:",tlbl->key+100);    
     CLRC;
+    _startLazyDPSEvaluation();
     while (size--) {
         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
         MOVA(l);
         emitcode("rrc","a");         
         aopPut(AOP(result),"a",offset--);
     }
+    _endLazyDPSEvaluation();
     reAdjustPreg(AOP(result));
 
     emitcode("","%05d$:",tlbl1->key+100);
@@ -6379,6 +6646,7 @@ static void genDataPointerGet (operand *left,
     /* get the string representation of the name */
     l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
     size = AOP_SIZE(result);
+    _startLazyDPSEvaluation();
     while (size--) {
        if (offset)
            sprintf(buffer,"(%s + %d)",l+1,offset);
@@ -6386,6 +6654,7 @@ static void genDataPointerGet (operand *left,
            sprintf(buffer,"%s",l+1);
        aopPut(AOP(result),buffer,offset++);
     }
+    _endLazyDPSEvaluation();
 
     freeAsmop(left,NULL,ic,TRUE);
     freeAsmop(result,NULL,ic,TRUE);
@@ -6588,14 +6857,12 @@ static void genFarPointerGet (operand *left,
         else 
         { 
             /* we need to get it byte by byte */
+            _startLazyDPSEvaluation();
            if (AOP_TYPE(left) != AOP_DPTR)
            {
                emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
                emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
-               if (options.model == MODEL_FLAT24)
-               {
-                           emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
-               }
+                       emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
             }
             else
             {
@@ -6607,6 +6874,7 @@ static void genFarPointerGet (operand *left,
                  emitcode("pop", "dph");
                  emitcode("pop", "dpl");
             }
+            _endLazyDPSEvaluation();
         }
     }
     /* so dptr know contains the address */
@@ -6649,12 +6917,11 @@ static void emitcodePointerGet (operand *left,
         if (AOP_TYPE(left) == AOP_IMMD)
             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
         else { /* we need to get it byte by byte */
+            _startLazyDPSEvaluation();
             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
-            if (options.model == MODEL_FLAT24)
-            {
-               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
-            }
+            emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
+            _endLazyDPSEvaluation();
         }
     }
     /* so dptr know contains the address */
@@ -6700,6 +6967,7 @@ static void genGenPointerGet (operand *left,
            emitcode("mov","b,#%d",pointerCode(retype));
        }
         else { /* we need to get it byte by byte */
+            _startLazyDPSEvaluation();
             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)
@@ -6711,6 +6979,7 @@ static void genGenPointerGet (operand *left,
             {
                emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
             }
+            _endLazyDPSEvaluation();
         }
     }
     /* so dptr know contains the address */
@@ -7175,14 +7444,12 @@ static void genFarPointerSet (operand *right,
         else 
         {
             /* we need to get it byte by byte */
+            _startLazyDPSEvaluation();
            if (AOP_TYPE(result) != AOP_DPTR)
            {
                emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
                emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
-               if (options.model == MODEL_FLAT24)
-               {
-                           emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
-               }
+                       emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
             }
             else
             {
@@ -7194,6 +7461,7 @@ static void genFarPointerSet (operand *right,
                  emitcode("pop", "dph");
                  emitcode("pop", "dpl");
             }
+            _endLazyDPSEvaluation();
         }
     }
     /* so dptr know contains the address */
@@ -7207,6 +7475,7 @@ static void genFarPointerSet (operand *right,
         size = AOP_SIZE(right);
         offset = 0 ;
 
+       _startLazyDPSEvaluation();
         while (size--) {
             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
             MOVA(l);
@@ -7214,6 +7483,7 @@ static void genFarPointerSet (operand *right,
             if (size)
                 emitcode("inc","dptr");
         }
+        _endLazyDPSEvaluation();
     }
 
     freeAsmop(right,NULL,ic,TRUE);
@@ -7233,6 +7503,7 @@ static void genGenPointerSet (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) {
+       _startLazyDPSEvaluation();
         /* if this is remateriazable */
         if (AOP_TYPE(result) == AOP_IMMD) {
             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
@@ -7241,16 +7512,10 @@ static void genGenPointerSet (operand *right,
         else { /* we need to get it byte by byte */
             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
-            if (options.model == MODEL_FLAT24)
-            {
-               emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
-               emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
-            }
-            else
-            {
-               emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
-            }
+            emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
+            emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
         }
+        _endLazyDPSEvaluation();
     }
     /* so dptr know contains the address */
     freeAsmop(result,NULL,ic,TRUE);
@@ -7459,14 +7724,16 @@ static void genFarFarAssign (operand *result, operand *right, iCode *ic)
     int size = AOP_SIZE(right);
     int offset = 0;
     char *l ;
+
+    D(emitcode(";", "genFarFarAssign "););
+
     /* first push the right side on to the stack */
+    _startLazyDPSEvaluation();
     while (size--) {
        l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
        MOVA(l);
        emitcode ("push","acc");
     }
-    
-    D(emitcode(";", "genFarFarAssign "););
 
     freeAsmop(right,NULL,ic,FALSE);
     /* now assign DPTR to result */
@@ -7477,6 +7744,7 @@ static void genFarFarAssign (operand *result, operand *right, iCode *ic)
        aopPut(AOP(result),"a",--offset);
     }
     freeAsmop(result,NULL,ic,FALSE);
+    _endLazyDPSEvaluation();
        
 }
 
@@ -7552,13 +7820,43 @@ static void genAssign (iCode *ic)
     offset = 0 ;
     if(AOP_TYPE(right) == AOP_LIT)
        lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+    
     if((size > 1) &&
        (AOP_TYPE(result) != AOP_REG) &&
        (AOP_TYPE(right) == AOP_LIT) &&
-       !IS_FLOAT(operandType(right)) &&
-       (lit < 256L)){
+       !IS_FLOAT(operandType(right)) 
+#ifndef LAZY_DPS_OPT       
+       && (lit < 256L)
+#endif       
+       )
+    {
+#ifdef LAZY_DPS_OPT    
+       D(emitcode(";", "Kevin's better literal load code"););
+       _startLazyDPSEvaluation();
+       while (size && ((unsigned int)((lit >> (offset*8)) & 0xff) != 0))
+       {
+           aopPut(AOP(result),
+                  aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
+                  offset);
+           offset++;
+           size--;
+       }
+       /* And now fill the rest with zeros. */
+       if (size)
+       {
+           emitcode("clr","a");
+       }
+       while (size--)
+       {
+           aopPut(AOP(result), "a", offset++);
+       }
+       _endLazyDPSEvaluation();
+#else
        emitcode("clr","a");
-       while (size--) {
+       
+       _startLazyDPSEvaluation();
+       while (size--) 
+       {
            if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
                aopPut(AOP(result),"a",size);
            else
@@ -7566,13 +7864,20 @@ static void genAssign (iCode *ic)
                       aopGet(AOP(right),size,FALSE,FALSE,FALSE),
                       size);
        }
-    } else {
-       while (size--) {
+       _endLazyDPSEvaluation();
+#endif 
+    } 
+    else 
+    {
+       _startLazyDPSEvaluation();
+       while (size--) 
+       {
            aopPut(AOP(result),
                   aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
                   offset);
            offset++;
        }
+       _endLazyDPSEvaluation();
     }
     
 release:
@@ -7581,7 +7886,7 @@ release:
 }   
 
 /*-----------------------------------------------------------------*/
-/* genJumpTab - genrates code for jump table                       */
+/* genJumpTab - generates code for jump table                      */
 /*-----------------------------------------------------------------*/
 static void genJumpTab (iCode *ic)
 {
@@ -7666,12 +7971,14 @@ static void genCast (iCode *ic)
         /* if they in different places then copy */
         size = AOP_SIZE(result);
         offset = 0 ;
+        _startLazyDPSEvaluation();
         while (size--) {
             aopPut(AOP(result),
                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
                    offset);
             offset++;
         }
+        _endLazyDPSEvaluation();
         goto release;
     }
 
@@ -7681,28 +7988,68 @@ static void genCast (iCode *ic)
 
        int p_type;
        link *type = operandType(right);
-       link *etype = getSpec(type);
 
        /* pointer to generic pointer */
        if (IS_GENPTR(ctype)) {
            char *l = zero;
            
            if (IS_PTR(type)) 
+           {
                p_type = DCL_TYPE(type);
-           else {
+           }
+           else 
+           {
+#if OLD_CAST_BEHAVIOR
+               /* KV: we are converting a non-pointer type to
+                * a generic pointer. This (ifdef'd out) code
+                * says that the resulting generic pointer 
+                * should have the same class as the storage
+                * location of the non-pointer variable.
+                * 
+                * For example, converting an int (which happens
+                * to be stored in DATA space) to a pointer results
+                * in a DATA generic pointer; if the original int
+                * in XDATA space, so will be the resulting pointer.
+                *
+                * I don't like that behavior, and thus this change:
+                * all such conversions will be forced to XDATA and
+                * throw a warning. If you want some non-XDATA
+                * type, or you want to suppress the warning, you
+                * must go through an intermediate cast, like so:
+                *
+                * char _generic *gp = (char _xdata *)(intVar);
+                */
+               link *etype = getSpec(type);             
+
                /* we have to go by the storage class */
-               p_type = PTR_TYPE(SPEC_OCLS(etype));
+               if (SPEC_OCLS(etype) != generic)
+               {
+                   p_type = PTR_TYPE(SPEC_OCLS(etype));
+               }
+               else
+#endif         
+               {
+                   /* Converting unknown class (i.e. register variable)
+                    * to generic pointer. This is not good, but
+                    * we'll make a guess (and throw a warning).
+                    */
+                   p_type = FPOINTER;
+                   werror(W_INT_TO_GEN_PTR_CAST);           
+               }
            }
                
            /* the first two bytes are known */
            size = GPTRSIZE - 1; 
            offset = 0 ;
+           _startLazyDPSEvaluation();
            while (size--) {
                aopPut(AOP(result),
                       aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
                       offset);
                offset++;
            }
+           _endLazyDPSEvaluation();
+           
            /* the last byte depending on type */
            switch (p_type) {
            case IPOINTER:
@@ -7721,7 +8068,7 @@ static void genCast (iCode *ic)
                
            default:
                /* this should never happen */
-        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+               werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
                       "got unknown pointer type");
                exit(1);
            }
@@ -7732,12 +8079,14 @@ static void genCast (iCode *ic)
        /* just copy the pointers */
        size = AOP_SIZE(result);
        offset = 0 ;
+       _startLazyDPSEvaluation();
        while (size--) {
            aopPut(AOP(result),
                   aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
                   offset);
            offset++;
        }
+       _endLazyDPSEvaluation();
        goto release ;
     }
     
@@ -7746,12 +8095,14 @@ static void genCast (iCode *ic)
     /* we move to result for the size of source */
     size = AOP_SIZE(right);
     offset = 0 ;
+    _startLazyDPSEvaluation();
     while (size--) {
         aopPut(AOP(result),
                aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
                offset);
         offset++;
     }
+    _endLazyDPSEvaluation();
 
     /* now depending on the sign of the source && destination */
     size = AOP_SIZE(result) - AOP_SIZE(right);