* device/lib/pic16/libsdcc/Makefile: added lregs directory in
[fw/sdcc] / src / pic16 / gen.c
index 2d130bc34f275ad83e3c45522da2fab4cfe305cf..159eeb8b559d304db8eb3f5cde1ea12488de16ab 100644 (file)
@@ -60,6 +60,8 @@ extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
 static void mov2w (asmop *aop, int offset);
 static void mov2f(asmop *dst, asmop *src, int offset);
 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
+static pCodeOp *pic16_popRegFromIdx(int rIdx);
+
 //static int aopIdx (asmop *aop, int offset);
 
 int pic16_labelOffset=0;
@@ -78,7 +80,6 @@ static int max_key=0;
 static int GpsuedoStkPtr=0;
 
 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
-pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
 
 unsigned int pic16aopLiteral (value *val, int offset);
 const char *pic16_AopType(short type);
@@ -137,6 +138,8 @@ static struct {
     int usefastretfie;
     bitVect *fregsUsed;
     int stack_lat;                     /* stack offset latency */
+    int resDirect;
+    int useWreg;                       /* flag when WREG is used to pass function parameter */
 } _G;
 
 /* Resolved ifx structure. This structure stores information
@@ -294,10 +297,16 @@ void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
   else
     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
-    
-//    fprintf(stderr, "%s\n", pcop->name);
 }
 
+void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
+{
+  if(pcop)
+    pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
+  else
+    DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
+}
+  
 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
 {
 
@@ -595,6 +604,8 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
 
     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
 
+    _G.resDirect = 0;  /* clear flag that instructs the result is loaded directly from aopForSym */
+    
 //    sym = OP_SYMBOL(op);
 
     /* if already has one */
@@ -628,10 +639,21 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
         aop->aopu.stk.stk = sym->stack;
         aop->size = getSize(sym->type);
 
-        for(i=0;i<aop->size;i++) {
-          aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
-          _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
-        }
+
+        DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
+        pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
+        if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
+          && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
+          
+          for(i=0;i<aop->size;i++)
+            aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
+            _G.resDirect = 1;  /* notify that result will be loaded directly from aopForSym */
+        } else
+          for(i=0;i<aop->size;i++) {
+            aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
+            _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
+          }
+
 
 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
 
@@ -722,6 +744,23 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
        return aop;
     }
 #endif
+
+#if 0
+    /* special case for a function */
+    if (IS_FUNC(sym->type)) {   
+        sym->aop = aop = newAsmop(AOP_PCODE);
+        //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
+       aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
+       PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
+       PCOI(aop->aopu.pcop)->index = 0;
+        aop->size = FPTRSIZE; 
+       DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
+        return aop;
+    }
+#endif
+
+
+
     //DEBUGpic16_emitcode(";","%d",__LINE__);
     /* if in bit space */
     if (IN_BITSPACE(space)) {
@@ -741,7 +780,8 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
         return aop;
     }
 
-    if (IN_FARSPACE(space)) {
+
+    if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
         sym->aop = aop = newAsmop (AOP_DIR);
         aop->aopu.aop_dir = sym->rname ;
         aop->size = getSize(sym->type);
@@ -750,22 +790,8 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
         return aop;
     }
 
-#if 0                                                                                          // patch 14
-    /* special case for a function */
-    if (IS_FUNC(sym->type)) {   
-        sym->aop = aop = newAsmop(AOP_IMMD);    
-        //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
-       aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
-        strcpy(aop->aopu.aop_immd,sym->rname);
-        aop->size = FPTRSIZE; 
-       DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
-        return aop;
-    }
-#endif                                                                                         // patch 14
-
 
     /* only remaining is far space */
-    /* in which case DPTR gets the address */
     sym->aop = aop = newAsmop(AOP_PCODE);
 
 /* change the next if to 1 to revert to good old immediate code */
@@ -814,6 +840,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
 static asmop *aopForRemat (operand *op) // x symbol *sym)
 {
   symbol *sym = OP_SYMBOL(op);
+  operand *refop;
   iCode *ic = NULL, *oldic;
   asmop *aop = newAsmop(AOP_PCODE);
   int val = 0;
@@ -845,14 +872,15 @@ static asmop *aopForRemat (operand *op) // x symbol *sym)
        }
 
        offset = OP_SYMBOL(IC_LEFT(ic))->offset;
+       refop = IC_LEFT(ic);
 
        if(!op->isaddr)viaimmd++; else viaimmd=0;
                
 /* set the following if to 1 to revert to good old immediate code */
-       if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
+       if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
                || viaimmd) {
 
-               DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
+               DEBUGpic16_emitcode(";", "%s:%d immediate", __FILE__, __LINE__);
 
                aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
 
@@ -864,7 +892,7 @@ static asmop *aopForRemat (operand *op) // x symbol *sym)
 
                PCOI(aop->aopu.pcop)->index = val;
        } else {
-               DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
+               DEBUGpic16_emitcode(";", "%s:%d dir", __FILE__, __LINE__);
 
                aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
                                getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
@@ -1000,23 +1028,38 @@ bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
 
     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
 
-#if 0
     if (aop1->type != AOP_REG ||
         aop2->type != AOP_REG )
         return FALSE ;
-#endif
 
     if (aop1->size != aop2->size )
         return FALSE ;
 
-    for (i = 0 ; i < aop1->size ; i++ )
-        if (aop1->aopu.aop_reg[i] !=
-            aop2->aopu.aop_reg[i] )
+    for (i = 0 ; i < aop1->size ; i++ ) {
+//        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
+
+//        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
+        if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
             return FALSE ;
+    }
 
     return TRUE ;
 }
 
+bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
+{
+    DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
+               pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
+
+    if(aop1 == aop2)return TRUE;
+    if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
+      
+      if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
+    
+  return TRUE;
+}
+
+
 /*-----------------------------------------------------------------*/
 /* pic16_aopOp - allocates an asmop for an operand  :                    */
 /*-----------------------------------------------------------------*/
@@ -1094,8 +1137,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
         /* rematerialize it NOW */
         if (sym->remat) {
 
-            sym->aop = op->aop = aop =
-                                      aopForRemat (op);
+            sym->aop = op->aop = aop = aopForRemat (op);
             aop->size = getSize(sym->type);
            //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
             return;
@@ -1255,8 +1297,11 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
               }
 
-              for(i=0;i<aop->size;i++)
-                PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
+              if(!_G.resDirect) {
+                for(i=0;i<aop->size;i++)
+                  PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
+              }
+              _G.resDirect = 0;
           }
           break;
 #if 0
@@ -1669,9 +1714,11 @@ static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand
   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
 
   /* make sure that register doesn't exist,
-   * and operand isn't NULL */
+   * and operand isn't NULL
+   * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
   if((PCOR(pcop)->r == NULL) 
-    && (op)) {
+    && (op)
+    && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
 //     fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
 //             __FUNCTION__, __LINE__, str, size, offset);
 
@@ -2167,6 +2214,7 @@ static void mov2f(asmop *dst, asmop *src, int offset)
     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
   } else {
+    if(pic16_sameRegsOfs(src, dst, offset))return;
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
                       pic16_popGet(dst, offset)));
   }
@@ -2781,35 +2829,34 @@ static void assignResultValue(operand * oper, int rescall)
       int areg = 0;            /* matching argument register */
       
       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
-      /* its called from genReceive (probably) */
-      if(!GpsuedoStkPtr) {
+
+
+      /* its called from genReceive (probably) -- VR */
+      if(!GpsuedoStkPtr && _G.useWreg) {
 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
+
         /* The last byte in the assignment is in W */
         if(areg <= GpsuedoStkPtr) {
           size--;
           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
           offset++;
         }
-       GpsuedoStkPtr++;
-       _G.stack_lat = AOP_SIZE(oper)-1;
       }
+//      GpsuedoStkPtr++;
+      _G.stack_lat = AOP_SIZE(oper)-1;
 
       while (size) {
-//        DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
-//        DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
-        if(areg <= GpsuedoStkPtr) {
-          size--;
-          popaopidx(AOP(oper), offset, GpsuedoStkPtr);
-          offset++;
-        }
-       GpsuedoStkPtr++;
+        size--;
+        GpsuedoStkPtr++;
+        popaopidx(AOP(oper), offset, GpsuedoStkPtr);
+        offset++;
       }
     }
 }
 
 
 /*-----------------------------------------------------------------*/
-/* genIpush - genrate code for pushing this gets a little complex  */
+/* genIpush - generate code for pushing this gets a little complex */
 /*-----------------------------------------------------------------*/
 static void genIpush (iCode *ic)
 {
@@ -2991,6 +3038,7 @@ static void genCall (iCode *ic)
   sym_link *ftype;   
   int stackParms=0;
   int use_wreg=0;
+  char *fname;
   
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
@@ -3002,6 +3050,11 @@ static void genCall (iCode *ic)
        /* initialise stackParms for IPUSH pushes */
 //     stackParms = psuedoStkPtr;
 //     fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
+    fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
+
+#if 0
+    gpsimDebug_StackDump(__FILE__, __LINE__, fname );
+#endif
 
     /* if send set is not empty the assign */
     if (_G.sendSet) {
@@ -3026,9 +3079,11 @@ static void genCall (iCode *ic)
         }
 */
 
+
 //        stackParms = psuedoStkPtr;
         stackParms = 0;
-
+        use_wreg = 0;
+        
         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
           int size, offset = 0;
 
@@ -3062,56 +3117,60 @@ static void genCall (iCode *ic)
           }
 
           /* save last parameter to stack if functions has varargs */
-          if(IFFUNC_HASVARARGS(ftype))
-                  pushw();
-          else
-            use_wreg = 1;              /* last parameter in WREG */
+          if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype))pushw();
+          else use_wreg = 1;           /* last parameter in WREG */
           
           _G.stackRegSet = _G.sendSet;
           _G.sendSet = NULL;
-      }
+    }
 
-      /* make the call */
-      pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
-                      OP_SYMBOL(IC_LEFT(ic))->rname :
-                      OP_SYMBOL(IC_LEFT(ic))->name));
+    /* make the call */
+    pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
 
-      GpsuedoStkPtr=0;
-      /* if we need to assign a result value */
-      if ((IS_ITEMP(IC_RESULT(ic))
-            && (OP_SYMBOL(IC_RESULT(ic))->nRegs
-                || OP_SYMBOL(IC_RESULT(ic))->spildir ))
-          || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
+    GpsuedoStkPtr=0;
+    /* if we need to assign a result value */
+    if ((IS_ITEMP(IC_RESULT(ic))
+          && (OP_SYMBOL(IC_RESULT(ic))->nRegs
+              || OP_SYMBOL(IC_RESULT(ic))->spildir ))
+        || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
 
-        _G.accInUse++;
-        pic16_aopOp(IC_RESULT(ic),ic,FALSE);
-        _G.accInUse--;
+      _G.accInUse++;
+      pic16_aopOp(IC_RESULT(ic),ic,FALSE);
+      _G.accInUse--;
 
-        assignResultValue(IC_RESULT(ic), 1);
+      assignResultValue(IC_RESULT(ic), 1);
 
-        DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
-                  pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
+      DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
+                pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
                
-        pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
-      }
+      pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
+    }
 
-      if(!stackParms && ic->parmBytes) {
-        stackParms = ic->parmBytes;
-      }
+    if(!stackParms && ic->parmBytes) {
+      stackParms = ic->parmBytes;
+    }
       
-      stackParms -= use_wreg;
+    stackParms -= use_wreg;
       
-      if(stackParms>0) {
+    if(stackParms>0) {
+      if(stackParms == 1) {
+        pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
+      } else {
         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
-        if(STACK_MODEL_LARGE) {
-          emitSKPNC;
-          pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
-        }
       }
+      if(STACK_MODEL_LARGE) {
+        emitSKPNC;
+        pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
+      }
+    }
+
+#if 0
+    gpsimDebug_StackDump(__FILE__, __LINE__, fname);
+#endif
 
-      /* adjust the stack for parameters if required */
-//      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
+    /* adjust the stack for parameters if required */
+//    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
 
 #if 0
       /* if register bank was saved then pop them */
@@ -3205,10 +3264,8 @@ static void genPcall (iCode *ic)
           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
       }
 
-      if(IFFUNC_HASVARARGS(ftype))
-        pushw();
-      else
-        use_wreg = 1;          /* last parameter in WREG */
+      if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype))pushw();
+      else use_wreg = 1;               /* last parameter in WREG */
 
       _G.stackRegSet = _G.sendSet;
       _G.sendSet = NULL;
@@ -3227,7 +3284,7 @@ static void genPcall (iCode *ic)
     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
-  
+
     /* make the call by writing the pointer into pc */
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
@@ -3329,269 +3386,192 @@ static void genFunction (iCode *ic)
   symbol *sym;
   sym_link *ftype;
   
-       DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
+    DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
 
-       pic16_labelOffset += (max_key+4);
-       max_key=0;
-       GpsuedoStkPtr=0;
-       _G.nRegsSaved = 0;
+    pic16_labelOffset += (max_key+4);
+    max_key=0;
+    GpsuedoStkPtr=0;
+    _G.nRegsSaved = 0;
        
-       ftype = operandType(IC_LEFT(ic));
-       sym = OP_SYMBOL(IC_LEFT(ic));
+    ftype = operandType(IC_LEFT(ic));
+    sym = OP_SYMBOL(IC_LEFT(ic));
 
-       if(IFFUNC_ISISR(sym->type /*ftype*/)) {
-               /* create an absolute section at the interrupt vector:
-                * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
-         symbol *asym;
-         char asymname[128];
-         pBlock *apb;
+    if(IFFUNC_ISISR(sym->type /*ftype*/)) {
+      /* create an absolute section at the interrupt vector:
+       * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
+      symbol *asym;
+      char asymname[128];
+      pBlock *apb;
 
-               {
-                 int i, found=-1;
-
-                       sym = OP_SYMBOL( IC_LEFT(ic));
-                       for(i=0;i<=2;i++) {
-                               if(interrupts[i]->name
-                                       && !STRCASECMP(interrupts[i]->name, sym->name)) {
-                                       found = i;
-                                       break;
-                               }
-                       }
+        {
+          int i, found=-1;
+
+            sym = OP_SYMBOL( IC_LEFT(ic));
+            for(i=0;i<=2;i++) {
+              if(interrupts[i]->name
+                    && !STRCASECMP(interrupts[i]->name, sym->name)) {
+                  found = i;
+                  break;
+              }
+            }
                        
-                       if(found == -1) {
-                               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
-                                       __FILE__, __LINE__, sym->name);
-                               assert( 0 );
-                       }
-                       _G.interruptvector = found;
-               }
-
-               sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
-               asym = newSymbol(asymname, 0);
-
-               apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
-               pic16_addpBlock( apb );
-
-               pic16_addpCode2pBlock(apb,
-                       pic16_newpCodeCharP(";-----------------------------------------"));
+            if(found == -1) {
+              fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
+                            __FILE__, __LINE__, sym->name);
+              assert( 0 );
+            }
+            _G.interruptvector = found;
+        }
 
+        sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
+        asym = newSymbol(asymname, 0);
 
-               pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
+        apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
+        pic16_addpBlock( apb );
 
-               pic16_addpCode2pBlock(apb,
-                       pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
+        pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
+        pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
+        pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
                
-               /* mark the end of this tiny function */
-               pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
-
-               {
-                 absSym *abSym;
+        /* mark the end of this tiny function */
+        pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
 
-                       abSym = Safe_calloc(1, sizeof(absSym));
-                       abSym->name = Safe_strdup( asymname );
-
-                       switch( _G.interruptvector ) {
-                               case 0: abSym->address = 0x000000; break;
-                               case 1: abSym->address = 0x000008; break;
-                               case 2: abSym->address = 0x000018; break;
-                       }
-
-                       /* relocate interrupt vectors if needed */
-                       abSym->address += pic16_options.ivt_loc;
-
-                       addSet(&absSymSet, abSym);
-               }
-       }
+       {
+         absSym *abSym;
 
+           abSym = Safe_calloc(1, sizeof(absSym));
+           strcpy(abSym->name, asymname);
 
-       /* create the function header */
-       pic16_emitcode(";","-----------------------------------------");
-       pic16_emitcode(";"," function %s",sym->name);
-       pic16_emitcode(";","-----------------------------------------");
+           switch( _G.interruptvector ) {
+             case 0: abSym->address = 0x000000; break;
+              case 1: abSym->address = 0x000008; break;
+              case 2: abSym->address = 0x000018; break;
+            }
 
-       pic16_emitcode("","%s:",sym->rname);
-       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
+            /* relocate interrupt vectors if needed */
+            abSym->address += pic16_options.ivt_loc;
 
+            addSet(&absSymSet, abSym);
+        }
+    }
 
-       {
-         absSym *ab;
+    /* create the function header */
+    pic16_emitcode(";","-----------------------------------------");
+    pic16_emitcode(";"," function %s",sym->name);
+    pic16_emitcode(";","-----------------------------------------");
 
-               for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
-                       if(!strcmp(ab->name, sym->name)) {
-                               pic16_pBlockConvert2Absolute(pb);
-                               break;
-                       }
+    pic16_emitcode("","%s:",sym->rname);
+    pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
 
-       }
 
+    {
+      absSym *ab;
 
-       if(IFFUNC_ISNAKED(ftype)) {
-               DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
-               return;
-       }
-       
-       /* if critical function then turn interrupts off */
-       if (IFFUNC_ISCRITICAL(ftype)) {
-         //pic16_emitcode("clr","ea");
+        for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
+          if(!strcmp(ab->name, sym->rname)) {
+            pic16_pBlockConvert2Absolute(pb);
+            break;
+          }
         }
+    }
 
-        _G.fregsUsed = sym->regsUsed;
-
-       /* if this is an interrupt service routine then
-        * save acc, b, dpl, dph  */
-       if (IFFUNC_ISISR(sym->type)) {
-         int i;
-
-               _G.usefastretfie = 1;   /* use shadow registers by default */
-               /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
-               if(!(_G.interruptvector == 1)) {
 
-                       /* do not save WREG,STATUS,BSR for high priority interrupts
-                        * because they are stored in the hardware shadow registers already */
-                       _G.usefastretfie = 0;
-                       pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
-                       pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
-                       pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
-               }
+    if(IFFUNC_ISNAKED(ftype)) {
+      DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
+      return;
+    }
+       
+    /* if critical function then turn interrupts off */
+    if (IFFUNC_ISCRITICAL(ftype)) {
+      //pic16_emitcode("clr","ea");
+    }
 
+    _G.fregsUsed = sym->regsUsed;
 
-                /* these should really be optimized somehow, because not all
-                 * interrupt handlers modify them */
-               pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
-               pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
-               pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
-               pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
+    /* if this is an interrupt service routine then
+     * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
+    if (IFFUNC_ISISR(sym->type)) {
+        _G.usefastretfie = 1;  /* use shadow registers by default */
+        
+        /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
+        if(!(_G.interruptvector == 1)) {
+          /* do not save WREG,STATUS,BSR for high priority interrupts
+           * because they are stored in the hardware shadow registers already */
+          _G.usefastretfie = 0;
+          pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
+          pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
+          pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
+        }
 
-//                pic16_pBlockConvert2ISR(pb);
+        /* these should really be optimized somehow, because not all
+         * interrupt handlers modify them */
+        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
+        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
+        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
+        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
+        
+//        pic16_pBlockConvert2ISR(pb);
                 
-               /* if any registers used */
-               if (sym->regsUsed) {
-                       /* save the registers used */
-                       DEBUGpic16_emitcode("; **", "Saving used registers in stack");
-                       for ( i = 0 ; i < sym->regsUsed->size ; i++) {
-                               if (bitVectBitValue(sym->regsUsed,i)) {
-#if 0
-                                       fprintf(stderr, "%s:%d function %s uses register %s\n",
-                                                       __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
-                                                       pic16_regWithIdx(i)->name);
-#endif
-
-                                       pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
-                                       _G.nRegsSaved++;
-
-                                       if(!pic16_regWithIdx(i)->wasUsed) {
-                                               fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
-                                                       __FILE__, __LINE__, pic16_regWithIdx(i)->name);
+    }
 
-                                               pic16_regWithIdx(i)->wasUsed = 1;
-                                       }
-                               }
-                       }
-               }
-       } else {
-               /* emit code to setup stack frame if user enabled,
-                * and function is not main() */
+    /* emit code to setup stack frame if user enabled,
+     * and function is not main() */
         
-//             fprintf(stderr, "function name: %s\n", sym->name);
-               if(strcmp(sym->name, "main")) {
-                       if(/*!options.ommitFramePtr || sym->regsUsed*/1) {
-                       /* setup the stack frame */
-                               pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
-                               pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
-                               if(STACK_MODEL_LARGE)
-                                       pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
-                       }
-               }
-
-               /* if callee-save to be used for this function
-               * then save the registers being used in this function */
-//             if (IFFUNC_CALLEESAVES(sym->type))
-               {
-                 int i;
-
-//                     fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
-
-//                     pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
-
-                       /* if any registers used */
-                       if (sym->regsUsed) {
-                               /* save the registers used */
-                               DEBUGpic16_emitcode("; **", "Saving used registers in stack");
-                               for ( i = 0 ; i < sym->regsUsed->size ; i++) {
-                                       if (bitVectBitValue(sym->regsUsed,i)) {
-
-#if 0
-                                               fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
-                                                               __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
-                                                               pic16_regWithIdx(i)->name,
-                                                               pic16_regWithIdx(i)->wasUsed,
-                                                               pic16_regWithIdx(i));
-#endif
-
-                                               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
-
-//                                             pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
-//                                                     PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
-//                                                     &pic16_pc_postdec1, 0));
+    //fprintf(stderr, "function name: %s\n", sym->name);
+    if(strcmp(sym->name, "main")) {
+      if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
+        /* setup the stack frame */
+        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
+        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
+        if(STACK_MODEL_LARGE)
+          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
+      }
+    }
 
-                                               _G.nRegsSaved++;
+    if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
+          && sym->stack) {
 
-                                               if(!pic16_regWithIdx(i)->wasUsed) {
-                                                       fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
-                                                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
+      if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
 
-                                                       pic16_regWithIdx(i)->wasUsed = 1;
-                                               }
-                                       
-                                       }
-                               }
-                       }
-               }
-       }
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
+      pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
+      emitSKPNC;
+      pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
+    }
+          
+    if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
+      _G.useWreg = 0;
+    else _G.useWreg = 1;
 
+    /* if callee-save to be used for this function
+     * then save the registers being used in this function */
+//    if (IFFUNC_CALLEESAVES(sym->type))
+    {
+      int i;
 
+        /* if any registers used */
+        if (sym->regsUsed) {
+          /* save the registers used */
+          DEBUGpic16_emitcode("; **", "Saving used registers in stack");
+          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
+          for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+            if (bitVectBitValue(sym->regsUsed,i)) {
+              pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
+              _G.nRegsSaved++;
+
+              if(!pic16_regWithIdx(i)->wasUsed) {
+                fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
+                              __FILE__, __LINE__, pic16_regWithIdx(i)->name);
+                pic16_regWithIdx(i)->wasUsed = 1;
+              }
+            }
+          }
+          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
+        }
+    }
        
-#if 0
-       if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
-
-               if (options.useXstack) {
-                       pic16_emitcode("mov","r0,%s",spname);
-                       pic16_emitcode("mov","a,_bp");
-                       pic16_emitcode("movx","@r0,a");
-                       pic16_emitcode("inc","%s",spname);
-               } else {
-                       /* set up the stack */
-                       pic16_emitcode ("push","_bp");     /* save the callers stack  */
-               }
-               pic16_emitcode ("mov","_bp,%s",spname);
-       }
-#endif
-       DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
-
-       /* adjust the stack for the function */
-       if (sym->stack) {
-         int i = sym->stack;
-
-               if (i > 127 ) 
-                       werror(W_STACK_OVERFLOW,sym->name);
-
-               if (i > 3 && sym->recvSize < 4) {              
-                       pic16_emitcode ("mov","a,sp");
-                       pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
-                       pic16_emitcode ("mov","sp,a");
-               } else
-                       while(i--)
-                               pic16_emitcode("inc","sp");
-       }
-
-       if (sym->xstack) {
-               DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
-
-               pic16_emitcode ("mov","a,_spx");
-               pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
-               pic16_emitcode ("mov","_spx,a");
-       }
-    
+    DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
+//    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3599,13 +3579,13 @@ static void genFunction (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genEndFunction (iCode *ic)
 {
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+  symbol *sym = OP_SYMBOL(IC_LEFT(ic));
 
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
     if(IFFUNC_ISNAKED(sym->type)) {
-       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
-       return;
+      DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
+      return;
     }
 
     _G.stack_lat = 0;
@@ -3617,172 +3597,109 @@ static void genEndFunction (iCode *ic)
       /* TODO: add code here -- VR */
     }
     
-
-#if 0
-    if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
-    {
-        pic16_emitcode ("mov","%s,_bp",spname);
+    if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
+          && sym->stack) {
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
+      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
+      emitSKPNC;
+      pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
     }
-#endif
 
-    /* if use external stack but some variables were
-    added to the local stack then decrement the
-    local stack */
-    if (options.useXstack && sym->stack) {      
-        pic16_emitcode("mov","a,sp");
-        pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
-        pic16_emitcode("mov","sp,a");
-    }
+    /* now we need to restore the registers */
+    /* if any registers used */
+    if (sym->regsUsed) {
+      int i;
 
+        pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
+        /* restore registers used */
+        DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
+        for ( i = sym->regsUsed->size; i >= 0; i--) {
+          if (bitVectBitValue(sym->regsUsed,i)) {
+            pic16_poppCodeOp( pic16_popRegFromIdx(i) );
+            _G.nRegsSaved--;
+          }
+        }
+        pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
 
-#if 0
-    if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
-       if (options.useXstack) {
-           pic16_emitcode("mov","r0,%s",spname);
-           pic16_emitcode("movx","a,@r0");
-           pic16_emitcode("mov","_bp,a");
-           pic16_emitcode("dec","%s",spname);
-       }
-       else
-       {
-           pic16_emitcode ("pop","_bp");
-       }
     }
-#endif
 
-       if (IFFUNC_ISISR(sym->type)) {
-               /* now we need to restore the registers */
-               /* if any registers used */
-               if (sym->regsUsed) {
-                 int i;
-
-                       /* restore registers used */
-                       DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
-                       for ( i = sym->regsUsed->size; i >= 0; i--) {
-                               if (bitVectBitValue(sym->regsUsed,i)) {
-
-//                                     fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
-//                                                     __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
-//                                                     pic16_regWithIdx(i)->name);
-
-                                       pic16_poppCodeOp( pic16_popRegFromIdx(i) );
+    if(strcmp(sym->name, "main")) {
+      if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
+        /* restore stack frame */
+        if(STACK_MODEL_LARGE)
+          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
+        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
+      }
+    }
 
-//                                     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
-//                                                     &pic16_pc_preinc1,
-//                                                     PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
+    _G.useWreg = 0;
 
-                               }
-                       }
-               }
-       
-               pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
-               pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
-               pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
-               pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
-
-               if(!(_G.interruptvector == 1)) {
-                       /* do not restore interrupt vector for WREG,STATUS,BSR
-                        * for high priority interrupt, see genFunction */
-                        
-                       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
-                       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
-                       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
-               }
-       
-               _G.interruptvector = 0;         /* sanity check */
+    if (IFFUNC_ISISR(sym->type)) {
+      pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
+      pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
+      pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
+      pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
 
-//             pic16_pBlockConvert2ISR(pb);
+      if(!(_G.interruptvector == 1)) {
+        /* do not restore interrupt vector for WREG,STATUS,BSR
+         * for high priority interrupt, see genFunction */
+       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
+       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
+       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
+      }
+      _G.interruptvector = 0;          /* sanity check */
 
 
-               /* if debug then send end of function */
-/*     if (options.debug && currFunc)  */
-               if (currFunc) {
-                       debugFile->writeEndFunction (currFunc, ic, 1);
-               }
-       
-               if(_G.usefastretfie)
-                       pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
-               else
-               pic16_emitpcodeNULLop(POC_RETFIE);
-               _G.usefastretfie = 0;
-       } else {
-               if (IFFUNC_ISCRITICAL(sym->type))
-                       pic16_emitcode("setb","ea");
+      /* if debug then send end of function */
+/*     if (options.debug && currFunc)  */
+      if (currFunc) {
+        debugFile->writeEndFunction (currFunc, ic, 1);
+      }
        
+      if(_G.usefastretfie)
+        pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
+      else
+        pic16_emitpcodeNULLop(POC_RETFIE);
 
-//             pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
+      pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
+      
+      _G.usefastretfie = 0;
+      return;
+    }
 
-               /* if any registers used */
-               if (sym->regsUsed) {
-                 int i;
-                       /* save the registers used */
-                       DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
-                       for ( i = sym->regsUsed->size; i >= 0; i--) {
-                               if (bitVectBitValue(sym->regsUsed,i)) {
-       
-//                                     fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
-//                                                     __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
-//                                                     pic16_regWithIdx(i)->name);
-       
-                                       pic16_poppCodeOp( pic16_popRegFromIdx(i) );
-                                       
-//                                     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
-//                                             &pic16_pc_preinc1,
-//                                             PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
+    if (IFFUNC_ISCRITICAL(sym->type)) {
+      pic16_emitcode("setb","ea");
+    }
 
-                                       _G.nRegsSaved--;
-                               }
-                       }
-               }
-       
-//             pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
-               /* if debug then send end of function */
-               if (currFunc) {
-                       debugFile->writeEndFunction (currFunc, ic, 1);
-               }
+    /* if debug then send end of function */
+    if (currFunc) {
+      debugFile->writeEndFunction (currFunc, ic, 1);
+    }
 
-               /* insert code to restore stack frame, if user enabled it
-                * and function is not main() */
+    /* insert code to restore stack frame, if user enabled it
+     * and function is not main() */
         
 
-               if(strcmp(sym->name, "main")) {
-                       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
-                               /* restore stack frame */
-                               if(STACK_MODEL_LARGE)
-                                       pic16_emitpcode(POC_MOVFF,
-                                               pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
-                               pic16_emitpcode(POC_MOVFF,
-                                               pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
-                       }
-               }
-
-               pic16_emitpcodeNULLop(POC_RETURN);
-
-               /* Mark the end of a function */
-               pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
-       }
+    pic16_emitpcodeNULLop(POC_RETURN);
 
+    /* Mark the end of a function */
+    pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
 }
 
 
 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
 {
-
-       if(is_LitOp(op)) {
-               pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
-
-               if(dest->type != PO_WREG)
-                       pic16_emitpcode(POC_MOVWF, dest);
-       } else {
-               if(dest->type == PO_WREG && (offset == 0)) {
-                       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
-                       return;
-               }
-               
-               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
-                       pic16_popGet(AOP(op), offset), dest));
-       }
-}
+  if(is_LitOp(op)) {
+    pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
+    if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
+  } else {
+    if(dest->type == PO_WREG && (offset == 0)) {
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
+      return;
+    }
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
+  }
+}
 
 /*-----------------------------------------------------------------*/
 /* genRet - generate code for return statement                     */
@@ -4695,6 +4612,7 @@ static int genChkZeroes(operand *op, int lit,  int size)
 /*-----------------------------------------------------------------*/
 /* genCmp :- greater or less than comparison                       */
 /*-----------------------------------------------------------------*/
+#if 1
 static void genCmp (operand *left,operand *right,
                     operand *result, iCode *ifx, int sign)
 {
@@ -4862,151 +4780,618 @@ static void genCmp (operand *left,operand *right,
 
        }
 
-       if(size == 1) {
+       if(size == 1) {
+
+         if( (lit & 0xff) == 0) {
+           /* lower byte is zero */
+           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+           i = ((lit >> 8) & 0xff) ^0x80;
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
+           genSkipc(&rFalseIfx);
+
+
+           if(ifx) ifx->generated = 1;
+           return;
+
+         }
+       } else {
+         /* Special cases for signed longs */
+         if( (lit & 0xffffff) == 0) {
+           /* lower byte is zero */
+           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+           i = ((lit >> 8*3) & 0xff) ^0x80;
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
+           genSkipc(&rFalseIfx);
+
+
+           if(ifx) ifx->generated = 1;
+           return;
+
+         }
+
+       }
+
+
+       if(lit & (0x80 << (size*8))) {
+         /* lit is negative */
+         DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+
+         //genSkipCond(&rFalseIfx,left,size,7);
+
+         pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+
+         if(rFalseIfx.condition)
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+         else
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+
+
+       } else {
+         /* lit is positive */
+         DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+         if(rFalseIfx.condition)
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+         else
+           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+       }
+
+       /*
+         This works, but is only good for ints.
+         It also requires a "known zero" register.
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
+         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
+         pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
+         pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
+         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
+         genSkipc(&rFalseIfx);
+
+         pic16_emitpLabel(truelbl->key);
+         if(ifx) ifx->generated = 1;
+         return;
+       **/
+         
+       /* There are no more special cases, so perform a general compare */
+  
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
+       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+
+       while(size--) {
+
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
+         emitSKPNZ;
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+       }
+       //rFalseIfx.condition ^= 1;
+       genSkipc(&rFalseIfx);
+
+       pic16_emitpLabel(truelbl->key);
+
+       if(ifx) ifx->generated = 1;
+       return;
+
+
+      }
+
+
+      /* sign is out of the way. So now do an unsigned compare */
+      DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
+
+
+      /* General case - compare to an unsigned literal on the right.*/
+
+      i = (lit >> (size*8)) & 0xff;
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+      while(size--) {
+       i = (lit >> (size*8)) & 0xff;
+
+       if(i) {
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+         emitSKPNZ;
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+       } else {
+         /* this byte of the lit is zero, 
+          *if it's not the last then OR in the variable */
+         if(size)
+           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
+       }
+      }
+
+
+      pic16_emitpLabel(lbl->key);
+//     pic16_emitpLabel(truelbl->key);
+      //if(emitFinalCheck)
+      genSkipc(&rFalseIfx);
+      if(sign)
+       pic16_emitpLabel(truelbl->key);
+
+      if(ifx) ifx->generated = 1;
+      return;
+
+
+    }
+#endif  // _swapp
+
+    if(AOP_TYPE(left) == AOP_LIT) {
+      //symbol *lbl = newiTempLabel(NULL);
+
+      //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
+
+
+      DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
+
+      /* Special cases */
+      if((lit == 0) && (sign == 0)){
+
+       size--;
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+       while(size) 
+         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
+
+       genSkipz2(&rFalseIfx,0);
+       if(ifx) ifx->generated = 1;
+       return;
+      }
+
+      if(size==1) {
+       /* Special cases */
+       lit &= 0xff;
+       if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
+         /* degenerate compare can never be true */
+         if(rFalseIfx.condition == 0)
+           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
+
+         if(ifx) ifx->generated = 1;
+         return;
+       }
+
+       if(sign) {
+         /* signed comparisons to a literal byte */
+
+         int lp1 = (lit+1) & 0xff;
+
+         DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
+         switch (lp1) {
+         case 0:
+           rFalseIfx.condition ^= 1;
+           genSkipCond(&rFalseIfx,right,0,7);
+           break;
+         case 0x7f:
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+           pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
+           genSkipz2(&rFalseIfx,1);
+           break;
+         default:
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
+           rFalseIfx.condition ^= 1;
+           genSkipc(&rFalseIfx);
+           break;
+         }
+       } else {
+         /* unsigned comparisons to a literal byte */
+
+         switch(lit & 0xff ) {
+         case 0:
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+           genSkipz2(&rFalseIfx,0);
+           break;
+         case 0x7f:
+           rFalseIfx.condition ^= 1;
+           genSkipCond(&rFalseIfx,right,0,7);
+           break;
+
+         default:
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
+           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
+           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+           rFalseIfx.condition ^= 1;
+           if (AOP_TYPE(result) == AOP_CRY)
+             genSkipc(&rFalseIfx);
+           else {
+             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+             pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
+           }         
+           break;
+         }
+       }
+
+       if(ifx) ifx->generated = 1;
+       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+               goto check_carry;
+       return;
+
+      } else {
+
+       /* Size is greater than 1 */
+
+       if(sign) {
+         int lp1 = lit+1;
+
+         size--;
+
+         if(lp1 == 0) {
+           /* this means lit = 0xffffffff, or -1 */
+
+
+           DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
+           rFalseIfx.condition ^= 1;
+           genSkipCond(&rFalseIfx,right,size,7);
+           if(ifx) ifx->generated = 1;
+
+           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+             goto check_carry;
+
+           return;
+         }
+
+         if(lit == 0) {
+           int s = size;
+
+           if(rFalseIfx.condition) {
+             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+           }
+
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+           while(size--)
+             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+
+
+           emitSKPZ;
+           if(rFalseIfx.condition) {
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+             pic16_emitpLabel(truelbl->key);
+           }else {
+             rFalseIfx.condition ^= 1;
+             genSkipCond(&rFalseIfx,right,s,7);
+           }
+
+           if(ifx) ifx->generated = 1;
+
+           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+             goto check_carry;
+
+           return;
+         }
+
+         if((size == 1) &&  (0 == (lp1&0xff))) {
+           /* lower byte of signed word is zero */
+           DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
+           i = ((lp1 >> 8) & 0xff) ^0x80;
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
+           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
+           rFalseIfx.condition ^= 1;
+           genSkipc(&rFalseIfx);
+
+
+           if(ifx) ifx->generated = 1;
+
+           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+             goto check_carry;
+
+           return;
+         }
+
+         if(lit & (0x80 << (size*8))) {
+           /* Lit is less than zero */
+           DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
+           //rFalseIfx.condition ^= 1;
+           //genSkipCond(&rFalseIfx,left,size,7);
+           //rFalseIfx.condition ^= 1;
+           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+           //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+           if(rFalseIfx.condition)
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+           else
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+
+         } else {
+           /* Lit is greater than or equal to zero */
+           DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
+           //rFalseIfx.condition ^= 1;
+           //genSkipCond(&rFalseIfx,right,size,7);
+           //rFalseIfx.condition ^= 1;
+
+           //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
+           //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+
+           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+           if(rFalseIfx.condition)
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+           else
+             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+
+         }
+
+
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+
+         while(size--) {
+
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
+           emitSKPNZ;
+           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+         }
+         rFalseIfx.condition ^= 1;
+         //rFalseIfx.condition = 1;
+         genSkipc(&rFalseIfx);
+
+         pic16_emitpLabel(truelbl->key);
+
+         if(ifx) ifx->generated = 1;
+
+
+          if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+            goto check_carry;
+
+         return;
+         // end of if (sign)
+       } else {
+
+         /* compare word or long to an unsigned literal on the right.*/
+
+
+         size--;
+         if(lit < 0xff) {
+           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
+           switch (lit) {
+           case 0:
+             break; /* handled above */
+/*
+           case 0xff:
+             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+             while(size--)
+               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+             genSkipz2(&rFalseIfx,0);
+             break;
+*/
+           default:
+             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+             while(--size)
+               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+
+             emitSKPZ;
+             if(rFalseIfx.condition)
+               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+             else
+               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+
+
+             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
+             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
+
+             rFalseIfx.condition ^= 1;
+             genSkipc(&rFalseIfx);
+           }
+
+           pic16_emitpLabel(truelbl->key);
+
+           if(ifx) ifx->generated = 1;
+
+            if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+              goto check_carry;
+
+           return;
+         }
+
+
+         lit++;
+         DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
+         i = (lit >> (size*8)) & 0xff;
+
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+
+         while(size--) {
+           i = (lit >> (size*8)) & 0xff;
+
+           if(i) {
+             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
+             emitSKPNZ;
+             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
+           } else {
+             /* this byte of the lit is zero, 
+              * if it's not the last then OR in the variable */
+             if(size)
+               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
+           }
+         }
+
+
+         pic16_emitpLabel(lbl->key);
+
+         rFalseIfx.condition ^= 1;
+
+         genSkipc(&rFalseIfx);
+       }
+
+       if(sign)
+         pic16_emitpLabel(truelbl->key);
+       if(ifx) ifx->generated = 1;
 
-         if( (lit & 0xff) == 0) {
-           /* lower byte is zero */
-           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
-           i = ((lit >> 8) & 0xff) ^0x80;
-           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
-           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
-           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
-           genSkipc(&rFalseIfx);
+            if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+              goto check_carry;
 
+       return;
+      }
+    }
+    /* Compare two variables */
 
-           if(ifx) ifx->generated = 1;
-           return;
+    DEBUGpic16_emitcode(";sign","%d",sign);
 
-         }
-       } else {
-         /* Special cases for signed longs */
-         if( (lit & 0xffffff) == 0) {
-           /* lower byte is zero */
-           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
-           i = ((lit >> 8*3) & 0xff) ^0x80;
-           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
-           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
-           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
-           genSkipc(&rFalseIfx);
+    size--;
+    if(sign) {
+      /* Sigh. thus sucks... */
+      if(size) {
+       pCodeOp *pctemp;
+       
+       pctemp = pic16_popGetTempReg(1);
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
+       pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
+       pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
+       pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
+       pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
+       pic16_popReleaseTempReg(pctemp, 1);
+      } else {
+       /* Signed char comparison */
+       /* Special thanks to Nikolai Golovchenko for this snippet */
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
+       pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
+       pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
+       pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
+       pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
 
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       genSkipc(&rFalseIfx);
+         
+       if(ifx) ifx->generated = 1;
 
-           if(ifx) ifx->generated = 1;
-           return;
+            if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+              goto check_carry;
 
-         }
+       return;
+      }
 
-       }
+    } else {
 
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
+    }
 
-       if(lit & (0x80 << (size*8))) {
-         /* lit is negative */
-         DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
 
-         //genSkipCond(&rFalseIfx,left,size,7);
+    /* The rest of the bytes of a multi-byte compare */
+    while (size) {
 
-         pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+      emitSKPZ;
+      pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
+      size--;
 
-         if(rFalseIfx.condition)
-           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
-         else
-           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
+      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
 
 
-       } else {
-         /* lit is positive */
-         DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
-         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-         if(rFalseIfx.condition)
-           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
-         else
-           pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
+    }
 
-       }
+    pic16_emitpLabel(lbl->key);
 
-       /*
-         This works, but is only good for ints.
-         It also requires a "known zero" register.
-         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
-         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
-         pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
-         pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
-         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
-         genSkipc(&rFalseIfx);
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
+       (AOP_TYPE(result) == AOP_REG)) {
+      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+      pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
+    } else {
+      genSkipc(&rFalseIfx);
+    }        
+    //genSkipc(&rFalseIfx);
+    if(ifx) ifx->generated = 1;
 
-         pic16_emitpLabel(truelbl->key);
-         if(ifx) ifx->generated = 1;
-         return;
-       **/
-         
-       /* There are no more special cases, so perform a general compare */
-  
-       pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
-       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
 
-       while(size--) {
+            if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+              goto check_carry;
 
-         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
-         emitSKPNZ;
-         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
-       }
-       //rFalseIfx.condition ^= 1;
-       genSkipc(&rFalseIfx);
+    return;
 
-       pic16_emitpLabel(truelbl->key);
+  }
 
-       if(ifx) ifx->generated = 1;
-       return;
+check_carry:
+  if ((AOP_TYPE(result) != AOP_CRY) 
+       && AOP_SIZE(result)) {
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
+    if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
 
-      }
+    pic16_outBitC(result);
+  } else {
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* if the result is used in the next
+       ifx conditional branch then generate
+       code a little differently */
+    if (ifx )
+      genIfxJump (ifx,"c");
+    else
+      pic16_outBitC(result);
+    /* leave the result in acc */
+  }
 
+}
 
-      /* sign is out of the way. So now do an unsigned compare */
-      DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
+#else  /* old version of genCmp() */
 
+/* new version of genCmp -- VR 20041012 */
+static void genCmp (operand *left,operand *right,
+                    operand *result, iCode *ifx, int sign)
+{
+  int size; //, offset = 0 ;
+  unsigned long lit = 0L,i = 0;
+  resolvedIfx rFalseIfx;
+  int willCheckCarry=0;
+  //  resolvedIfx rTrueIfx;
+  symbol *truelbl;
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-      /* General case - compare to an unsigned literal on the right.*/
 
-      i = (lit >> (size*8)) & 0xff;
-      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
-      pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
-      while(size--) {
-       i = (lit >> (size*8)) & 0xff;
+  /* General concept:
+   * subtract right from left if at the end the carry flag is set then we
+   * know that left is greater than right */
+            
+  resolveIfx(&rFalseIfx,ifx);
+  truelbl  = newiTempLabel(NULL);
+  size = max(AOP_SIZE(left),AOP_SIZE(right));
 
-       if(i) {
-         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
-         emitSKPNZ;
-         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
-       } else {
-         /* this byte of the lit is zero, 
-          *if it's not the last then OR in the variable */
-         if(size)
-           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
-       }
-      }
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
 
+  /* POC_CPFSGT        compare f, wreg, skip if f greater than wreg
+   * POC_CPFSLT compare f, wreg, skip if f less then wreg */
+  
 
-      pic16_emitpLabel(lbl->key);
-//     pic16_emitpLabel(truelbl->key);
-      //if(emitFinalCheck)
-      genSkipc(&rFalseIfx);
-      if(sign)
-       pic16_emitpLabel(truelbl->key);
+  /* if literal is on the right then swap with left */
+  if ((AOP_TYPE(right) == AOP_LIT)) {
+    operand *tmp = right ;
+    unsigned long mask = (0x100 << (8*(size-1))) - 1;
 
-      if(ifx) ifx->generated = 1;
-      return;
+      lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
 
+//      lit = (lit - 1) & mask;
+      right = left;
+      left = tmp;
+      rFalseIfx.condition ^= 1;
+  } else
+  if ((AOP_TYPE(left) == AOP_LIT)) {
+    /* float compares are handled by support functions */
+    lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
+  }
 
-    }
-#endif  // _swapp
 
-    if(AOP_TYPE(left) == AOP_LIT) {
-      //symbol *lbl = newiTempLabel(NULL);
+  //if(IC_TRUE(ifx) == NULL)
+  /* if left & right are bit variables */
+  if (AOP_TYPE(left) == AOP_CRY &&
+      AOP_TYPE(right) == AOP_CRY ) {
+    pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+    pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
 
-      //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
+  } else {
+    symbol *lbl  = newiTempLabel(NULL);
 
+    if(AOP_TYPE(left) == AOP_LIT) {
+      DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
 
-      DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
+      if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
+        willCheckCarry = 1;
+      else willCheckCarry = 0;
 
       /* Special cases */
       if((lit == 0) && (sign == 0)){
@@ -5038,7 +5423,7 @@ static void genCmp (operand *left,operand *right,
 
          int lp1 = (lit+1) & 0xff;
 
-         DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
+         DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d",__LINE__,lit, rFalseIfx.condition);
          switch (lp1) {
          case 0:
            rFalseIfx.condition ^= 1;
@@ -5050,11 +5435,27 @@ static void genCmp (operand *left,operand *right,
            genSkipz2(&rFalseIfx,1);
            break;
          default:
-           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
+           
+           if(rFalseIfx.condition)
+             pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
+            else
+              pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
+
+           if(willCheckCarry) {
+              if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
+              else { emitSETC; emitCLRC; }
+              
+            } else {
+              pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
+            }              
+                     
+/*         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
            pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
            pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
            rFalseIfx.condition ^= 1;
            genSkipc(&rFalseIfx);
+*/
            break;
          }
        } else {
@@ -5377,6 +5778,9 @@ check_carry:
   }
 
 }
+#endif
+
+
 
 /*-----------------------------------------------------------------*/
 /* genCmpGt :- greater than comparison                             */
@@ -10016,9 +10420,9 @@ static void genGenPointerGet (operand *left,
 
     } else { /* we need to get it byte by byte */
 
-      /* set up WREG:FSR0H:FSR0L with address from left */
+      /* set up WREG:PRODL:FSR0L with address from left */
       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
+      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
       
       switch( size ) {
@@ -10041,6 +10445,7 @@ static void genGenPointerGet (operand *left,
           sym = newSymbol( fgptrget, 0 );
           strcpy(sym->rname, fgptrget);
           checkAddSym(&externs, sym);
+
 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
       }
               
@@ -10432,19 +10837,32 @@ static void genDataPointerSet(operand *right,
 
        while (size--) {
                if (AOP_TYPE(right) == AOP_LIT) {
-                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
-
-                       lit = lit >> (8*offset);
-                       if(lit&0xff) {
-                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
-                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
-                       } else {
-                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
-                       }
-               } else {
-                       mov2w(AOP(right), offset);
-                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
-               }
+                 unsigned int lit;
+
+                   if(!IS_FLOAT(operandType( right )))
+                     lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+                    else {
+                      union {
+                        unsigned long lit_int;
+                        float lit_float;
+                      } info;
+       
+                        /* take care if literal is a float */
+                        info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+                        lit = info.lit_int;
+                    }
+
+                    lit = lit >> (8*offset);
+                    if(lit&0xff) {
+                      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
+                      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
+                    } else {
+                      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
+                    }
+                } else {
+                  mov2w(AOP(right), offset);
+                  pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
+                }
                offset++;
                resoffset++;
        }
@@ -10874,8 +11292,14 @@ static void genGenPointerSet (operand *right,
     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
 
 
-    /* load value to write in TBLPTRH:TBLPTRL:PRODH:PRODL */
-    mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(right), 0);
+
+    /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
+
+    /* value of right+0 is placed on stack, which will be retrieved
+     * by the support function this restoring the stack. The important
+     * thing is that there is no need to manually restore stack pointer
+     * here */
+    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
@@ -10884,7 +11308,7 @@ static void genGenPointerSet (operand *right,
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
-                                pic16_popCopyReg(&pic16_pc_fsr0h)));
+                                pic16_popCopyReg(&pic16_pc_prodl)));
     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
     
 
@@ -10892,6 +11316,7 @@ static void genGenPointerSet (operand *right,
     switch (size) {
       case 1: strcpy(fgptrput, "__gptrput1"); break;
       case 2: strcpy(fgptrput, "__gptrput2"); break;
+      case 3: strcpy(fgptrput, "__gptrput3"); break;
       case 4: strcpy(fgptrput, "__gptrput4"); break;
       default:
         werror(W_POSSBUG2, __FILE__, __LINE__);
@@ -10906,7 +11331,6 @@ static void genGenPointerSet (operand *right,
         sym = newSymbol( fgptrput, 0 );
         strcpy(sym->rname, fgptrput);
         checkAddSym(&externs, sym);
-//          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
     }
 
 release:
@@ -11149,8 +11573,11 @@ static void genAssign (iCode *ic)
   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
     return ;
 
-  pic16_aopOp(right,ic,FALSE);
+  /* reversed order operands are aopOp'ed so that result operand
+   * is effective in case right is a stack symbol. This maneauver
+   * allows to use the _G.resDirect flag later */
   pic16_aopOp(result,ic,TRUE);
+  pic16_aopOp(right,ic,FALSE);
 
   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
 
@@ -11229,16 +11656,20 @@ static void genAssign (iCode *ic)
 //                     sizeof(unsigned long int), sizeof(float));
 
   if(AOP_TYPE(right) != AOP_LIT
-       && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
+       && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
+       && !IS_FUNC(OP_SYM_TYPE(right))
+       ) {
        DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
-       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
+//     fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
 
        // set up table pointer
        if( (AOP_TYPE(right) == AOP_PCODE)
                && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
-               || (AOP(right)->aopu.pcop->type == PO_DIR)))
+//             || (AOP(right)->aopu.pcop->type == PO_DIR)
+                )
+               )
        {
-               fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
+//             fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
                pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
                pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
                pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
@@ -11246,7 +11677,7 @@ static void genAssign (iCode *ic)
                pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
                pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
        } else {
-               fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
+//             fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
                                pic16_popCopyReg(&pic16_pc_tblptrl)));
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
@@ -11317,32 +11748,15 @@ static void genAssign (iCode *ic)
        pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
        pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
     } else {
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-#if 1
-       /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
-          normally should work, but mind that the W register live range
-          is not checked, so if the code generator assumes that the W
-          is already loaded after such a pair, wrong code will be generated.
-          
-          Checking the live range is the next step.
-          This is experimental code yet and has not been fully tested yet.
-          USE WITH CARE. Revert to old code by setting 0 to the condition above.
-          Vangelis Rokas 030603 (vrokas@otenet.gr) */
-          
-       pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
-#else  
-       /* This is the old code, which is assumed(?!) that works fine(!?) */
-
-       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
-       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
-#endif
+      if(!_G.resDirect)                /* use this aopForSym feature */
+        pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
     }
            
     offset++;
   }
-
-    
+  
  release:
   pic16_freeAsmop (right,NULL,ic,FALSE);
   pic16_freeAsmop (result,NULL,ic,TRUE);
@@ -11800,9 +12214,7 @@ static void genCast (iCode *ic)
     size = AOP_SIZE(right);
     offset = 0 ;
     while (size--) {
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
-//      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
-//      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
+      mov2f(AOP(result), AOP(right), offset);
       offset++;
     }