Whoops! Minor garbage in previous checkin
[fw/sdcc] / src / mcs51 / gen.c
index 148c988e412ba72d34c1cda9911f9c64d0b03b3e..2121e19c0cc64f503e3bd4ed32be04ed531f5956 100644 (file)
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #else
+#ifndef __BORLANDC__
 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
 #endif
 #endif
+#endif
 
 #include "common.h"
 #include "SDCCpeeph.h"
@@ -60,7 +62,11 @@ char *aopLiteral (value *val, int offset);
 static char *zero = "#0x00";
 static char *one  = "#0x01";
 static char *spname ;
-static char *fReturn[] = {"dpl","dph","b","a" };
+
+char *fReturn8051[] = {"dpl","dph","b","a" };
+char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
+unsigned fReturnSize = 4; /* shared with ralloc.c */
+char **fReturn = fReturn8051;
 static char *accUse[] = {"a","b"};
 
 static short rbank = -1;
@@ -145,8 +151,9 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
     instruction, in which case we are in trouble */
     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
+    {
         goto endOfWorld;      
-
+    }
 
     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
@@ -155,6 +162,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
     if (!r0iu && !r0ou) {
         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
         (*aopp)->type = AOP_R0;
+        
         return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
     }
 
@@ -162,6 +170,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
     if (!r1iu && !r1ou) {
         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
         (*aopp)->type = AOP_R1;
+
         return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
     }    
 
@@ -174,7 +183,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
                       mcs51_regWithIdx(R0_IDX)->dname);
             _G.r0Pushed++ ;
         }
-
+        
         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
         (*aopp)->type = AOP_R0;
 
@@ -190,16 +199,15 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
                       mcs51_regWithIdx(R1_IDX)->dname);
             _G.r1Pushed++ ;
         }
-
+        
         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
         (*aopp)->type = AOP_R1;
         return mcs51_regWithIdx(R1_IDX);
     }
 
-
 endOfWorld :
     /* I said end of world but not quite end of world yet */
-    /* if this is a result then we canpush it on the stack*/
+    /* if this is a result then we can push it on the stack*/
     if (result) {
         (*aopp)->type = AOP_STK;    
         return NULL;
@@ -230,21 +238,24 @@ static asmop *newAsmop (short type)
 static int pointerCode (link *etype)
 {
     int p_type;
-    if (SPEC_OCLS(etype)->codesp ) {
-       p_type = CPOINTER ;     
-    }
-    else
-       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
-           p_type = FPOINTER ;
-       else
-           if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
-               p_type = PPOINTER;
-           else
-               if (SPEC_OCLS(etype) == idata )
-                   p_type = IPOINTER;
-               else
-                   p_type = POINTER ;
-    return p_type;
+
+    return PTR_TYPE(SPEC_OCLS(etype));
+
+/*     if (SPEC_OCLS(etype)->codesp ) { */
+/*     p_type = CPOINTER ;      */
+/*     } */
+/*     else */
+/*     if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*         p_type = FPOINTER ; */
+/*     else */
+/*         if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*             p_type = PPOINTER; */
+/*         else */
+/*             if (SPEC_OCLS(etype) == idata ) */
+/*                 p_type = IPOINTER; */
+/*             else */
+/*                 p_type = POINTER ; */
+/*     return p_type; */
 }
 
 /*-----------------------------------------------------------------*/
@@ -262,7 +273,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
     /* assign depending on the storage class */
     /* if it is on the stack or indirectly addressable */
     /* space we need to assign either r0 or r1 to it   */    
-    if (sym->onStack || sym->iaccess) {
+    if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
         sym->aop = aop = newAsmop(0);
         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
         aop->size = getSize(sym->type);
@@ -272,7 +283,6 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
         if (aop->type != AOP_STK) {
 
             if (sym->onStack) {
-
                     if ( _G.accInUse )
                         emitcode("push","acc");
 
@@ -286,7 +296,6 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
 
                     if ( _G.accInUse )
                         emitcode("pop","acc");
-
             } else
                 emitcode("mov","%s,#%s",
                          aop->aopu.aop_ptr->name,
@@ -296,6 +305,56 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
             aop->aopu.aop_stk = sym->stack;
         return aop;
     }
+    
+    if (sym->onStack && options.stack10bit)
+    {
+        /* It's on the 10 bit stack, which is located in
+         * far data space.
+         */
+         
+         if (result)
+         {
+             fprintf(stderr, 
+                    "*** Internal error: 10 bit stack var used as result.\n");
+             emitcode(";", "look at me!");
+         }
+         
+        
+        if ( _G.accInUse )
+               emitcode("push","acc");
+
+        emitcode("mov","a,_bp");
+        emitcode("add","a,#0x%02x",
+                 ((sym->stack < 0) ?
+                   ((char)(sym->stack - _G.nRegsSaved )) :
+                   ((char)sym->stack)) & 0xff);
+        
+        if (/* result */ 1)
+        {
+            emitcode (";", "#switchDPTR(2)");
+        }
+       emitcode ("mov","dpx,#0x40");
+       emitcode ("mov","dph,#0x00");
+       emitcode ("mov", "dpl, a");
+       if (/* result */ 1)
+       {
+           emitcode (";", "#switchDPTR(1)");
+       }
+       
+        if ( _G.accInUse )
+            emitcode("pop","acc");
+            
+        if (/* !result */ 0)
+        {
+           sym->aop = aop = newAsmop(AOP_DPTR);
+       }
+       else
+       {
+           sym->aop = aop = newAsmop(AOP_DPTR2);
+       }
+       aop->size = getSize(sym->type); 
+       return aop;
+    }
 
     /* if in bit space */
     if (IN_BITSPACE(space)) {
@@ -317,7 +376,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
         sym->aop = aop = newAsmop(AOP_IMMD);    
         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
         strcpy(aop->aopu.aop_immd,sym->rname);
-        aop->size = 2;
+        aop->size = FPTRSIZE; 
         return aop;
     }
 
@@ -549,7 +608,7 @@ static void aopOp (operand *op, iCode *ic, bool result)
             int i;
             aop = op->aop = sym->aop = newAsmop(AOP_STR);
             aop->size = getSize(sym->type);
-            for ( i = 0 ; i < 4 ; i++ )
+            for ( i = 0 ; i < fReturnSize ; i++ )
                 aop->aopu.aop_str[i] = fReturn[i];
             return;
         }
@@ -619,12 +678,23 @@ static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
             bitVectUnSetBit(ic->rUsed,R1_IDX);          
 
             getFreePtr(ic,&aop,FALSE);
+            
+            if (options.stack10bit)
+            {
+                /* I'm not sure what to do here yet... */
+                /* #STUB */
+               fprintf(stderr, 
+                       "*** Warning: probably generating bad code for "
+                       "10 bit stack mode.\n");
+            }
+            
             if (stk) {
                 emitcode ("mov","a,_bp");
                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
-            } else
+            } else {
                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
+            }
 
             while (sz--) {
                 emitcode("pop","acc");
@@ -700,6 +770,13 @@ static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
        return rs;
        
     case AOP_DPTR:
+    case AOP_DPTR2:
+    
+       if (aop->type == AOP_DPTR2)
+       {
+           emitcode (";", "#switchDPTR(2)");
+       }
+    
        while (offset > aop->coff) {
            emitcode ("inc","dptr");
            aop->coff++;
@@ -717,6 +794,12 @@ static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
         }
        else
            emitcode("movx","a,@dptr");
+           
+       if (aop->type == AOP_DPTR2)
+       {
+           emitcode (";", "#switchDPTR(1)");
+       }           
+           
        return (dname ? "acc" : "a");
        
        
@@ -830,6 +913,13 @@ static void aopPut (asmop *aop, char *s, int offset)
        break;
        
     case AOP_DPTR:
+    case AOP_DPTR2:
+    
+        if (aop->type == AOP_DPTR2)
+       {
+           emitcode (";", "#switchDPTR(2)");
+       }
+    
        if (aop->code) {
            werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
                   "aopPut writting to code space");
@@ -852,6 +942,11 @@ static void aopPut (asmop *aop, char *s, int offset)
        MOVA(s);        
        
        emitcode ("movx","@dptr,a");
+       
+    if (aop->type == AOP_DPTR2)
+       {
+           emitcode (";", "#switchDPTR(1)");
+       }       
        break;
        
     case AOP_R0:
@@ -919,10 +1014,11 @@ static void aopPut (asmop *aop, char *s, int offset)
                        
                        if (strcmp(s,"a")) {
                            MOVA(s);
-                       }  
-                       emitcode("cjne","a,#0x01,%05d$",lbl->key+100);
-                       emitcode("","%05d$:",lbl->key+100);
+                       }
+                       emitcode("clr","c");
+                       emitcode("jz","%05d$",lbl->key+100);
                        emitcode("cpl","c");
+                       emitcode("","%05d$:",lbl->key+100);
                        emitcode("mov","%s,c",aop->aopu.aop_dir);
                    }
        }
@@ -995,9 +1091,19 @@ static void reAdjustPreg (asmop *aop)
             while (size--)
                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
             break;          
-        case AOP_DPTR : 
+        case AOP_DPTR :
+        case AOP_DPTR2:
+            if (aop->type == AOP_DPTR2)
+           {
+               emitcode (";", "#switchDPTR(2)");
+           } 
             while (size--)
                 emitcode("lcall","__decdptr");
+                
+           if (aop->type == AOP_DPTR2)
+           {
+               emitcode (";", "#switchDPTR(1)");
+           }                
             break;  
 
     }   
@@ -1011,7 +1117,8 @@ static void reAdjustPreg (asmop *aop)
                        AOP_TYPE(x) == AOP_R0))
 
 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
-                        AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged)) 
+                        AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
+                         AOP(x)->paged)) 
 
 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
@@ -1055,6 +1162,21 @@ static void genNotFloat (operand *op, operand *res)
         aopPut(res->aop,zero,offset++);
 }
 
+/*-----------------------------------------------------------------*/
+/* opIsGptr: returns non-zero if the passed operand is            */   
+/* a generic pointer type.                                        */
+/*-----------------------------------------------------------------*/ 
+static int opIsGptr(operand *op)
+{
+    link *type = operandType(op);
+    
+    if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
+    {
+        return 1;
+    }
+    return 0;        
+}
+
 /*-----------------------------------------------------------------*/
 /* getDataSize - get the operand data size                         */
 /*-----------------------------------------------------------------*/
@@ -1062,9 +1184,17 @@ static int getDataSize(operand *op)
 {
     int size;
     size = AOP_SIZE(op);
-    if(size == 3)
-        /* pointer */
-        size--;
+    if (size == GPTRSIZE)
+    {
+        link *type = operandType(op);
+        if (IS_GENPTR(type))
+        {
+            /* generic pointer; arithmetic operations
+             * should ignore the high byte (pointer type).
+             */
+            size--;
+        }
+    }
     return size;
 }
 
@@ -1739,11 +1869,17 @@ static void genPcall (iCode *ic)
     emitcode("push","acc");    
     emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
     emitcode("push","acc");
+    
+    if (options.model == MODEL_FLAT24)
+    {
+       emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
+       emitcode("push","acc");    
+    }
 
     /* now push the calling address */
     aopOp(IC_LEFT(ic),ic,FALSE);
 
-    pushSide(IC_LEFT(ic), 2);
+    pushSide(IC_LEFT(ic), FPTRSIZE);
 
     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
 
@@ -1833,6 +1969,12 @@ static int resultRemat (iCode *ic)
     return 0;
 }
 
+#ifdef __BORLANDC__
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
 /*-----------------------------------------------------------------*/
 /* inExcludeList - return 1 if the string is in exclude Reg list   */
 /*-----------------------------------------------------------------*/
@@ -1841,12 +1983,12 @@ static bool inExcludeList(char *s)
     int i =0;
     
     if (options.excludeRegs[i] &&
-       strcasecmp(options.excludeRegs[i],"none") == 0)
+    STRCASECMP(options.excludeRegs[i],"none") == 0)
        return FALSE ;
 
     for ( i = 0 ; options.excludeRegs[i]; i++) {
        if (options.excludeRegs[i] &&
-           strcasecmp(s,options.excludeRegs[i]) == 0)
+        STRCASECMP(s,options.excludeRegs[i]) == 0)
            return TRUE;
     }
     return FALSE ;
@@ -1904,7 +2046,8 @@ static void genFunction (iCode *ic)
            emitcode ("push","dpl");
        if (!inExcludeList("dph"))
            emitcode ("push","dph");
-       
+       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+           emitcode ("push", "dpx");   
        /* if this isr has no bank i.e. is going to
           run with bank 0 , then we need to save more
           registers :-) */
@@ -1968,8 +2111,10 @@ static void genFunction (iCode *ic)
            emitcode("inc","%s",spname);
        }
        else
+       {
            /* set up the stack */
            emitcode ("push","_bp");     /* save the callers stack  */
+       }
        emitcode ("mov","_bp,%s",spname);
     }
 
@@ -2009,7 +2154,9 @@ static void genEndFunction (iCode *ic)
     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
 
     if (IS_RENT(sym->etype) || options.stackAuto)
+    {
         emitcode ("mov","%s,_bp",spname);
+    }
 
     /* if use external stack but some variables were
     added to the local stack then decrement the
@@ -2029,7 +2176,9 @@ static void genEndFunction (iCode *ic)
            emitcode("dec","%s",spname);
        }
        else
+       {
            emitcode ("pop","_bp");
+       }
     }
 
     /* restore the register bank  */    
@@ -2068,6 +2217,8 @@ static void genEndFunction (iCode *ic)
            }       
        }
 
+       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+           emitcode ("pop", "dpx");
        if (!inExcludeList("dph"))
            emitcode ("pop","dph");
        if (!inExcludeList("dpl"))
@@ -2154,6 +2305,7 @@ static void genRet (iCode *ic)
     while (size--) {
            char *l ;
            if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
+                   /* #NOCHANGE */
                    l = aopGet(AOP(IC_LEFT(ic)),offset++,
                           FALSE,TRUE);
                    emitcode("push","%s",l);
@@ -2207,6 +2359,33 @@ static void genGoto (iCode *ic)
     emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
 }
 
+/*-----------------------------------------------------------------*/
+/* findLabelBackwards: walks back through the iCode chain looking  */
+/* for the given label. Returns number of iCode instructions      */
+/* between that label and given ic.                               */
+/* Returns zero if label not found.                               */
+/*-----------------------------------------------------------------*/
+static int findLabelBackwards(iCode *ic, int key)
+{
+    int count = 0;
+    
+    while (ic->prev)
+    {
+        ic = ic->prev;
+        count++;
+        
+        if (ic->op == LABEL && IC_LABEL(ic)->key == key)
+        {
+            /* printf("findLabelBackwards = %d\n", count); */
+            return count;
+        }
+    }
+    
+    /* printf("findLabelBackwards: not found.\n"); */
+    
+    return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* genPlusIncr :- does addition with increment if possible         */
 /*-----------------------------------------------------------------*/
@@ -2230,7 +2409,27 @@ static bool genPlusIncr (iCode *ic)
     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
         (size > 1) &&
         (icount == 1)) {
-        symbol *tlbl = newiTempLabel(NULL);
+        symbol *tlbl;
+        int emitTlbl;
+        int labelRange;
+
+       /* If the next instruction is a goto and the goto target
+        * is < 10 instructions previous to this, we can generate
+        * jumps straight to that target.
+        */
+        if (ic->next && ic->next->op == GOTO
+            && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
+            && labelRange <= 10 )
+        {
+           emitcode(";", "tail increment optimized");
+           tlbl = IC_LABEL(ic->next);
+           emitTlbl = 0;
+        }
+        else
+        {
+            tlbl = newiTempLabel(NULL);
+            emitTlbl = 1;
+        }
        emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
        if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
           IS_AOP_PREG(IC_RESULT(ic)))
@@ -2245,7 +2444,8 @@ static bool genPlusIncr (iCode *ic)
        }
     
        emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
-       if(size == 4){
+       if (size > 2)
+       {
            if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
               IS_AOP_PREG(IC_RESULT(ic)))
                emitcode("cjne","%s,#0x00,%05d$"
@@ -2257,6 +2457,9 @@ static bool genPlusIncr (iCode *ic)
                         ,tlbl->key+100);
            
            emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
+       }
+       if (size > 3)
+       {
            if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
               IS_AOP_PREG(IC_RESULT(ic)))
                emitcode("cjne","%s,#0x00,%05d$"
@@ -2269,7 +2472,11 @@ static bool genPlusIncr (iCode *ic)
            }
            emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
        }
-       emitcode("","%05d$:",tlbl->key+100);
+       
+       if (emitTlbl)
+       {
+           emitcode("","%05d$:",tlbl->key+100);
+       }
         return TRUE;
     }
     
@@ -2340,6 +2547,75 @@ static void genPlusBits (iCode *ic)
     }
 }
 
+#if 0
+/* This is the original version of this code.
+ *
+ * This is being kept around for reference, 
+ * because I am not entirely sure I got it right...
+ */
+static void adjustArithmeticResult(iCode *ic)
+{
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_LEFT(ic)) == 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
+              2);
+
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
+              2);
+    
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
+       AOP_SIZE(IC_LEFT(ic)) < 3    &&
+       AOP_SIZE(IC_RIGHT(ic)) < 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
+       char buffer[5];
+       sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
+       aopPut(AOP(IC_RESULT(ic)),buffer,2);
+    }
+}
+#else
+/* This is the pure and virtuous version of this code.
+ * I'm pretty certain it's right, but not enough to toss the old 
+ * code just yet...
+ */
+static void adjustArithmeticResult(iCode *ic)
+{
+    if (opIsGptr(IC_RESULT(ic)) &&
+       opIsGptr(IC_LEFT(ic))   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+    {
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
+              GPTRSIZE - 1);
+    }
+
+    if (opIsGptr(IC_RESULT(ic)) &&
+        opIsGptr(IC_RIGHT(ic))   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
+    {
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
+              GPTRSIZE - 1);
+    }
+
+    if (opIsGptr(IC_RESULT(ic))           &&
+        AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
+        AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
+        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
+        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
+        char buffer[5];
+        sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
+        aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
+     }
+}
+#endif
+
 /*-----------------------------------------------------------------*/
 /* genPlus - generates code for addition                           */
 /*-----------------------------------------------------------------*/
@@ -2420,29 +2696,8 @@ static void genPlus (iCode *ic)
         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
     }
 
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_LEFT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
-              2);
+    adjustArithmeticResult(ic);
 
-     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
-              2);
-     
-     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
-        AOP_SIZE(IC_LEFT(ic)) < 3    &&
-        AOP_SIZE(IC_RIGHT(ic)) < 3   &&
-        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
-        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
-        char buffer[5];
-        sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
-        aopPut(AOP(IC_RESULT(ic)),buffer,2);
-     }
 release:
     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
@@ -2455,7 +2710,7 @@ release:
 static bool genMinusDec (iCode *ic)
 {
     unsigned int icount ;
-       unsigned int size = getDataSize(IC_RESULT(ic));
+    unsigned int size = getDataSize(IC_RESULT(ic));
 
     /* will try to generate an increment */
     /* if the right side is not a literal 
@@ -2468,12 +2723,32 @@ static bool genMinusDec (iCode *ic)
     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
         return FALSE ;
 
-       size = getDataSize(IC_RESULT(ic));
     /* if decrement 16 bits in register */
     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
         (size > 1) &&
         (icount == 1)) {
-        symbol *tlbl = newiTempLabel(NULL);
+            symbol *tlbl;
+            int emitTlbl;
+            int labelRange;
+
+           /* If the next instruction is a goto and the goto target
+            * is <= 10 instructions previous to this, we can generate
+            * jumps straight to that target.
+            */
+            if (ic->next && ic->next->op == GOTO
+                && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
+                && labelRange <= 10 )
+            {        
+               emitcode(";", "tail decrement optimized");
+               tlbl = IC_LABEL(ic->next);
+               emitTlbl = 0;
+            }
+            else
+            {
+                tlbl = newiTempLabel(NULL);
+                emitTlbl = 1;
+            }
+        
                emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
                if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
                   IS_AOP_PREG(IC_RESULT(ic)))
@@ -2487,7 +2762,8 @@ static bool genMinusDec (iCode *ic)
                                         ,tlbl->key+100);
                }
                emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
-               if(size == 4){
+               if (size > 2)
+               {
                        if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
                           IS_AOP_PREG(IC_RESULT(ic)))
                                emitcode("cjne","%s,#0xff,%05d$"
@@ -2499,6 +2775,9 @@ static bool genMinusDec (iCode *ic)
                                                 ,tlbl->key+100);
                        }
                        emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
+               }
+               if (size > 3)
+               {
                        if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
                           IS_AOP_PREG(IC_RESULT(ic)))
                                emitcode("cjne","%s,#0xff,%05d$"
@@ -2511,7 +2790,10 @@ static bool genMinusDec (iCode *ic)
                        }
                        emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
                }
-               emitcode("","%05d$:",tlbl->key+100);
+               if (emitTlbl)
+               {
+                   emitcode("","%05d$:",tlbl->key+100);
+               }
         return TRUE;
     }
 
@@ -2628,30 +2910,9 @@ static void genMinus (iCode *ic)
         }
         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
     }
-    
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_LEFT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
-              2);
 
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
-              2);
-    
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
-       AOP_SIZE(IC_LEFT(ic)) < 3    &&
-       AOP_SIZE(IC_RIGHT(ic)) < 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
-       char buffer[5];
-       sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
-       aopPut(AOP(IC_RESULT(ic)),buffer,2);
-    }
+    adjustArithmeticResult(ic);
+        
 release:
     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
@@ -4161,12 +4422,13 @@ static void genXor (iCode *ic, iCode *ifx)
                 // c = bit ^ val
                 // if val>>1 != 0, result = 1
                 emitcode("setb","c");
-                while(sizer--){
+                while(sizer){
                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
                     if(sizer == 1)
                         // test the msb of the lsb
                         emitcode("anl","a,#0xfe");
                     emitcode("jnz","%05d$",tlbl->key+100);
+                   sizer--;
                 }
                 // val = (0,1)
                 emitcode("rrc","a");
@@ -4876,10 +5138,9 @@ static void genlshOne (operand *result, operand *left, int shCount)
 /*-----------------------------------------------------------------*/
 static void genlshTwo (operand *result,operand *left, int shCount)
 {
-    int size = AOP_SIZE(result);
-
-    if (size == 3)
-        size--;
+    int size;
+    
+    size = getDataSize(result);
 
     /* if shCount >= 8 */
     if (shCount >= 8) {
@@ -5909,6 +6170,10 @@ static void genFarPointerGet (operand *left,
         else { /* we need to get it byte by byte */
             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+            }
         }
     }
     /* so dptr know contains the address */
@@ -5953,6 +6218,10 @@ static void emitcodePointerGet (operand *left,
         else { /* we need to get it byte by byte */
             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+            }
         }
     }
     /* so dptr know contains the address */
@@ -6000,12 +6269,20 @@ static void genGenPointerGet (operand *left,
         else { /* we need to get it byte by byte */
             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
-            emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+               emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
+            }
+            else
+            {
+               emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
+            }
         }
     }
     /* so dptr know contains the address */
     freeAsmop(left,NULL,ic,TRUE);
-    aopOp(result,ic,FALSE);
+    aopOp(result,ic,FALSE); 
 
     /* if bit then unpack */
     if (IS_BITVAR(retype)) 
@@ -6045,22 +6322,23 @@ static void genPointerGet (iCode *ic)
     if (IS_PTR(type) && !IS_FUNC(type->next)) 
         p_type = DCL_TYPE(type);
     else {
-
        /* we have to go by the storage class */
-       if (SPEC_OCLS(etype)->codesp ) {
-           p_type = CPOINTER ; 
-       }
-       else
-           if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
-               p_type = FPOINTER ;
-           else
-               if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
-                   p_type = PPOINTER;
-               else
-                   if (SPEC_OCLS(etype) == idata )
-                       p_type = IPOINTER;
-                   else
-                       p_type = POINTER ;
+       p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+/*     if (SPEC_OCLS(etype)->codesp ) { */
+/*         p_type = CPOINTER ;  */
+/*     } */
+/*     else */
+/*         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*             p_type = FPOINTER ; */
+/*         else */
+/*             if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*                 p_type = PPOINTER; */
+/*             else */
+/*                 if (SPEC_OCLS(etype) == idata ) */
+/*                     p_type = IPOINTER; */
+/*                 else */
+/*                     p_type = POINTER ; */
     }
 
     /* now that we have the pointer type we assign
@@ -6462,6 +6740,10 @@ static void genFarPointerSet (operand *right,
         else { /* we need to get it byte by byte */
             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
+            }
         }
     }
     /* so dptr know contains the address */
@@ -6509,7 +6791,15 @@ static void genGenPointerSet (operand *right,
         else { /* we need to get it byte by byte */
             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
-            emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
+               emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
+            }
+            else
+            {
+               emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
+            }
         }
     }
     /* so dptr know contains the address */
@@ -6556,22 +6846,23 @@ static void genPointerSet (iCode *ic)
         p_type = DCL_TYPE(type);
     }
     else {
-
        /* we have to go by the storage class */
-       if (SPEC_OCLS(etype)->codesp ) {
-           p_type = CPOINTER ; 
-       }
-       else
-           if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
-               p_type = FPOINTER ;
-           else
-               if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
-                   p_type = PPOINTER ;
-               else
-                   if (SPEC_OCLS(etype) == idata )
-                       p_type = IPOINTER ;
-                   else
-                       p_type = POINTER ;
+       p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+/*     if (SPEC_OCLS(etype)->codesp ) { */
+/*         p_type = CPOINTER ;  */
+/*     } */
+/*     else */
+/*         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*             p_type = FPOINTER ; */
+/*         else */
+/*             if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*                 p_type = PPOINTER ; */
+/*             else */
+/*                 if (SPEC_OCLS(etype) == idata ) */
+/*                     p_type = IPOINTER ; */
+/*                 else */
+/*                     p_type = POINTER ; */
     }
 
     /* now that we have the pointer type we assign
@@ -6653,14 +6944,33 @@ static void genAddrOf (iCode *ic)
             emitcode("mov","a,_bp");
             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
             aopPut(AOP(IC_RESULT(ic)),"a",0);       
-        } else 
+        } else {
             /* we can just move _bp */
             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
+        }
         /* fill the result with zero */
         size = AOP_SIZE(IC_RESULT(ic)) - 1;
+        
+        
+        if (options.stack10bit && size < (FPTRSIZE - 1))
+        {
+            fprintf(stderr, 
+                   "*** warning: pointer to stack var truncated.\n");
+        }
+        
         offset = 1;
-        while (size--) 
-            aopPut(AOP(IC_RESULT(ic)),zero,offset++);
+        while (size--)
+        {
+            /* Yuck! */
+            if (options.stack10bit && offset == 2)
+            {
+                aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
+            }
+            else
+            {
+               aopPut(AOP(IC_RESULT(ic)),zero,offset++);
+            }
+        }
 
         goto release;
     }
@@ -6731,12 +7041,26 @@ static void genAssign (iCode *ic)
     aopOp(right,ic,FALSE);
     
     /* special case both in far space */
+    /* However, if we are using 10 bit stack mode,
+     * the result should be held in DPTR2,
+     * so we can operate without the special case.
+     *
+     * I think.
+     */
     if (AOP_TYPE(right) == AOP_DPTR &&
        IS_TRUE_SYMOP(result)       &&
        isOperandInFarSpace(result)) {
-
-       genFarFarAssign (result,right,ic);
-        return ;
+       
+       if (!options.stack10bit)
+       {
+           genFarFarAssign (result,right,ic);
+            return ;
+        }
+        else
+        {
+            fprintf(stderr, "*** 10bit stack opt 1\n");
+            emitcode(";", "look at me: optimization possible?\n");
+        }
     }
 
     aopOp(result,ic,TRUE);
@@ -6905,60 +7229,62 @@ static void genCast (iCode *ic)
 
        /* pointer to generic pointer */
        if (IS_GENPTR(ctype)) {
-               char *l = zero;
-
-               if (IS_PTR(type)) 
-                       p_type = DCL_TYPE(type);
-               else {
-                       /* we have to go by the storage class */
-                       if (SPEC_OCLS(etype)->codesp ) 
-                               p_type = CPOINTER ;     
-                       else
-                               if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
-                                       p_type = FPOINTER ;
-                               else
-                                       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
-                                               p_type = PPOINTER;
-                                       else
-                                               if (SPEC_OCLS(etype) == idata )
-                                                       p_type = IPOINTER ;
-                                               else
-                                                       p_type = POINTER ;
-               }
+           char *l = zero;
+           
+           if (IS_PTR(type)) 
+               p_type = DCL_TYPE(type);
+           else {
+               /* we have to go by the storage class */
+               p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+/*             if (SPEC_OCLS(etype)->codesp )  */
+/*                 p_type = CPOINTER ;  */
+/*             else */
+/*                 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*                     p_type = FPOINTER ; */
+/*                 else */
+/*                     if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*                         p_type = PPOINTER; */
+/*                     else */
+/*                         if (SPEC_OCLS(etype) == idata ) */
+/*                             p_type = IPOINTER ; */
+/*                         else */
+/*                             p_type = POINTER ; */
+           }
                
-               /* the first two bytes are known */
-               size = 2;
-               offset = 0 ;
-               while (size--) {
-                       aopPut(AOP(result),
-                              aopGet(AOP(right),offset,FALSE,FALSE),
-                              offset);
-                       offset++;
-               }
-               /* the last byte depending on type */
-               switch (p_type) {
-               case IPOINTER:
-               case POINTER:
-                       l = zero;
-                       break;
-               case FPOINTER:
-                       l = one;
-                       break;
-               case CPOINTER:
-                       l = "#0x02";
-                       break;                          
-               case PPOINTER:
-                       l = "#0x03";
-                       break;
-                       
-               default:
-                       /* this should never happen */
-                       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-                              "got unknown pointer type");
-                       exit(1);
-               }
-               aopPut(AOP(result),l,2);            
-               goto release ;
+           /* the first two bytes are known */
+           size = GPTRSIZE - 1; 
+           offset = 0 ;
+           while (size--) {
+               aopPut(AOP(result),
+                      aopGet(AOP(right),offset,FALSE,FALSE),
+                      offset);
+               offset++;
+           }
+           /* the last byte depending on type */
+           switch (p_type) {
+           case IPOINTER:
+           case POINTER:
+               l = zero;
+               break;
+           case FPOINTER:
+               l = one;
+               break;
+           case CPOINTER:
+               l = "#0x02";
+               break;                          
+           case PPOINTER:
+               l = "#0x03";
+               break;
+               
+           default:
+               /* this should never happen */
+               werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                      "got unknown pointer type");
+               exit(1);
+           }
+           aopPut(AOP(result),l, GPTRSIZE - 1);            
+           goto release ;
        }
        
        /* just copy the pointers */
@@ -7073,10 +7399,10 @@ static void genReceive (iCode *ic)
          IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
 
        int size = getSize(operandType(IC_RESULT(ic)));
-       int offset =  4 - size;
+       int offset =  fReturnSize - size;
        while (size--) {
-           emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
-                                   fReturn[3 - offset] : "acc"));
+           emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
+                                   fReturn[fReturnSize - offset - 1] : "acc"));
            offset++;
        }
        aopOp(IC_RESULT(ic),ic,FALSE);