* as/xa51/xa_version.h,
[fw/sdcc] / src / pic16 / gen.c
index efc10964894e0fccf037dba2e32ea089b2e88cbd..19d484ebef5fab41e6b81725bf47bfc29a086bde 100644 (file)
@@ -72,6 +72,8 @@ static int optimized_for_speed = 0;
 
 */
 
+extern set *externs;
+
 /* max_key keeps track of the largest label number used in 
    a function. This is then used to adjust the label offset
    for the next function.
@@ -94,6 +96,11 @@ static bool is_LitAOp(asmop *aop);
 
 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
 
+/* set the following macro to 1 to enable passing the
+ * first byte of functions parameters via WREG */
+#define USE_WREG_IN_FUNC_PARAMS        0
+
+
 /* this is the down and dirty file with all kinds of 
    kludgy & hacky stuff. This is what it is all about
    CODE GENERATION for a specific MCU . some of the
@@ -139,6 +146,7 @@ static struct {
     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
@@ -296,10 +304,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)
 {
 
@@ -737,6 +751,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)) {
@@ -756,7 +787,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);
@@ -765,22 +797,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 */
@@ -2219,18 +2237,38 @@ static void mov2fp(pCodeOp *dst, asmop *src, int offset)
   }
 }
 
+void pic16_testStackOverflow(void)
+{
+#define        GSTACK_TEST_NAME        "__gstack_test"
+
+  pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
+  
+  {
+    symbol *sym;
+
+      sym = newSymbol( GSTACK_TEST_NAME , 0 );
+      strcpy(sym->rname, GSTACK_TEST_NAME);
+      checkAddSym(&externs, sym);
+  }
+
+}
 
 /* push pcop into stack */
 void pic16_pushpCodeOp(pCodeOp *pcop)
 {
 //     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
+  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
+  if(pic16_options.gstack)
+    pic16_testStackOverflow();
+    
 }
 
 /* pop pcop from stack */
 void pic16_poppCodeOp(pCodeOp *pcop)
 {
-       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
+  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
+  if(pic16_options.gstack)
+    pic16_testStackOverflow();
 }
 
 
@@ -2239,8 +2277,10 @@ void pic16_poppCodeOp(pCodeOp *pcop)
 /*-----------------------------------------------------------------*/
 void pushw(void)
 {
-        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
+  if(pic16_options.gstack)
+    pic16_testStackOverflow();
 }
 
                 
@@ -2249,8 +2289,19 @@ void pushw(void)
 /*-----------------------------------------------------------------*/
 void pushaop(asmop *aop, int offset)
 {
-        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-        pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(is_LitAOp(aop)) {
+    pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
+  } else {
+    pic16_emitpcode(POC_MOVFF,
+      pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
+  }
+
+//  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
+  if(pic16_options.gstack)
+    pic16_testStackOverflow();
 }
 
 /*-----------------------------------------------------------------*/
@@ -2258,20 +2309,24 @@ void pushaop(asmop *aop, int offset)
 /*-----------------------------------------------------------------*/
 void popaop(asmop *aop, int offset)
 {
-       DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
-       pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
+  DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
+  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
+  if(pic16_options.gstack)
+    pic16_testStackOverflow();
 }
 
 void popaopidx(asmop *aop, int offset, int index)
 {
   int ofs=1;
 
-        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-       if(STACK_MODEL_LARGE)ofs++;
+    if(STACK_MODEL_LARGE)ofs++;
 
-       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
-        pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
+    pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
+    pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
+    if(pic16_options.gstack)
+      pic16_testStackOverflow();
 }
 
 /*-----------------------------------------------------------------*/
@@ -2759,7 +2814,7 @@ void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
 
 /*-----------------------------------------------------------------*/
 /* assignResultValue - assign results to oper, rescall==1 is       */
-/*                     called from genCall() or genPCall()         */
+/*                     called from genCall() or genPcall()         */
 /*-----------------------------------------------------------------*/
 static void assignResultValue(operand * oper, int rescall)
 {
@@ -2798,6 +2853,7 @@ static void assignResultValue(operand * oper, int rescall)
         /* >32-bits, result on stack, and FSR0 points to beginning.
         * Fix stack when done */
        /* FIXME FIXME */
+//     debugf("WARNING: Possible bug when returning more than 4-bytes\n");
        while (size--) {
 //         DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
@@ -2817,36 +2873,38 @@ static void assignResultValue(operand * oper, int rescall)
     } else {
       int areg = 0;            /* matching argument register */
       
+//      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
       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++;
+//          debugf("receive from WREG\n", 0);
         }
-       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);
+//        debugf("receive from STACK\n", 0);
+        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)
 {
@@ -2854,7 +2912,6 @@ static void genIpush (iCode *ic)
 
   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
 
-
   if(ic->parmPush) {
     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
 
@@ -3020,6 +3077,17 @@ static void saverbank (int bank, iCode *ic, bool pushPsw)
 #endif /* 0 */
 
 
+static int wparamCmp(void *p1, void *p2)
+{
+  return (!strcmp((char *)p1, (char *)p2));
+}
+
+int inWparamList(char *s)
+{
+  return isinSetWith(wparamList, s, wparamCmp);
+} 
+
+
 /*-----------------------------------------------------------------*/
 /* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
@@ -3028,6 +3096,7 @@ static void genCall (iCode *ic)
   sym_link *ftype;   
   int stackParms=0;
   int use_wreg=0;
+  int inwparam=0;
   char *fname;
   
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
@@ -3041,6 +3110,7 @@ static void genCall (iCode *ic)
 //     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;
+    inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
 
 #if 0
     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
@@ -3053,63 +3123,74 @@ static void genCall (iCode *ic)
       int firstTimeThruLoop = 1;
 
 
-#if 1
         /* reverse sendSet if function is not reentrant */
         if(!IFFUNC_ISREENT(ftype))
           _G.sendSet = reverseSet(_G.sendSet);
-#endif
 
        /* First figure how many parameters are getting passed */
-
-/*     do we really need to know this ? -- VR 
-       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
-         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
-          psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
-          pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
-        }
-*/
-
-
-//        stackParms = psuedoStkPtr;
         stackParms = 0;
         use_wreg = 0;
         
         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
-          int size, offset = 0;
+          int size;
+//          int offset = 0;
 
             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
             size = AOP_SIZE(IC_LEFT(sic));
 
             stackParms += size;
 
-            while (size--) {
-              DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
-                    pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
-              DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
+            /* pass the last byte through WREG */
+            if(inwparam) {
 
-              if(!firstTimeThruLoop) {
-                /* If this is not the first time we've been through the loop
-                 * then we need to save the parameter in a temporary
-                 * register. The last byte of the last parameter is
-                 * passed in W. */
+              while (size--) {
+                DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
+                      pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
+                DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
 
-                pushw();
-//                --psuedoStkPtr;              // sanity check
-              }
+                if(!firstTimeThruLoop) {
+                  /* If this is not the first time we've been through the loop
+                   * then we need to save the parameter in a temporary
+                   * register. The last byte of the last parameter is
+                   * passed in W. */
+
+                  pushw();
+//                  --psuedoStkPtr;            // sanity check
+                  use_wreg = 1;
+                }
                 
-              firstTimeThruLoop=0;
+                firstTimeThruLoop=0;
+
+                mov2w (AOP(IC_LEFT(sic)), size);
 
-              mov2w (AOP(IC_LEFT(sic)), size);
+//                offset++;
+              }
+            } else {
+              /* all arguments are passed via stack */
+              use_wreg = 0;
 
-              offset++;
+              while (size--) {
+                DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
+                      pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
+                DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
+
+//                pushaop(AOP(IC_LEFT(sic)), size);
+                mov2w (AOP(IC_LEFT(sic)), size);
+                pushw();
+              }
             }
+
             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
           }
 
-          /* save last parameter to stack if functions has varargs */
-          if(IFFUNC_HASVARARGS(ftype))pushw();
-          else use_wreg = 1;           /* last parameter in WREG */
-          
+          if(inwparam) {
+            if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
+              pushw(); /* save last parameter to stack if functions has varargs */
+              use_wreg = 0;
+            } else
+              use_wreg = 1;
+          } else use_wreg = 0;
+
           _G.stackRegSet = _G.sendSet;
           _G.sendSet = NULL;
     }
@@ -3118,6 +3199,7 @@ static void genCall (iCode *ic)
     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
@@ -3141,10 +3223,14 @@ static void genCall (iCode *ic)
     }
       
     stackParms -= use_wreg;
-      
+    
     if(stackParms>0) {
-      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
+      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 ));
@@ -3177,84 +3263,48 @@ static void genCall (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genPcall (iCode *ic)
 {
-  sym_link *ftype;
+  sym_link *ftype, *fntype;
   int stackParms=0;
   symbol *retlbl = newiTempLabel(NULL);
   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
-  int use_wreg=0;
   
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
     ftype = OP_SYM_TYPE(IC_LEFT(ic));
-    
+    fntype = operandType( IC_LEFT(ic) )->next;
+
     /* if send set is not empty the assign */
     if (_G.sendSet) {
       iCode *sic;
       int psuedoStkPtr=-1; 
-      int firstTimeThruLoop = 1;
-
-      /* For the Pic port, there is no data stack.
-       * So parameters passed to functions are stored
-       * in registers. (The pCode optimizer will get
-       * rid of most of these :). */
 
-
-#if 1
       /* reverse sendSet if function is not reentrant */
-      if(!IFFUNC_ISREENT(ftype))
+      if(!IFFUNC_ISREENT(fntype))
         _G.sendSet = reverseSet(_G.sendSet);
-#endif
-
-      /* First figure how many parameters are getting passed */
-#if 0
-      for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
-        pic16_aopOp(IC_LEFT(sic),sic,FALSE);
-        psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
-        pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
-      }
-#endif
 
-//      stackParms = psuedoStkPtr;
       stackParms = 0;
-
+      
       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
-        int size, offset = 0;
+        int size;
 
           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
           size = AOP_SIZE(IC_LEFT(sic));
           stackParms += size;
 
+          /* all parameters are passed via stack, since WREG is clobbered
+           * by the calling sequence */
           while (size--) {
             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
 
-            if(!firstTimeThruLoop) {
-              /* If this is not the first time we've been through the loop
-               * then we need to save the parameter in a temporary
-               * register. The last byte of the last parameter is
-               * passed in W. */
-
-              pushw();
-              --psuedoStkPtr;          // sanity check
-            }
-                       
-            firstTimeThruLoop=0;
-
             mov2w (AOP(IC_LEFT(sic)), size);
-
-            offset++;
+            pushw();
           }
 
-
           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
       }
 
-      if(IFFUNC_HASVARARGS(ftype))
-        pushw();
-      else
-        use_wreg = 1;          /* last parameter in WREG */
-
       _G.stackRegSet = _G.sendSet;
       _G.sendSet = NULL;
     }
@@ -3272,7 +3322,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)));
@@ -3306,7 +3356,7 @@ static void genPcall (iCode *ic)
       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
     }
 
-    stackParms -= use_wreg;
+//    stackParms -= use_wreg;
     
     if(stackParms>0) {
       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
@@ -3374,269 +3424,199 @@ 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 */
+        if(STACK_MODEL_LARGE)
+          pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
+        pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
+//        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(inWparamList(sym->name)) {
+      if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
+        _G.useWreg = 0;
+      else
+        _G.useWreg = 1;
+    } else
+      _G.useWreg = 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;
 
+        /* 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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3644,13 +3624,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;
@@ -3662,171 +3642,110 @@ 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;
+    if(strcmp(sym->name, "main")) {
+      if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
+        /* restore stack frame */
+        if(STACK_MODEL_LARGE)
+          pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
+//          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
+        pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
+//        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
+      }
+    }
 
-                       /* restore registers used */
-                       DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
-                       for ( i = sym->regsUsed->size; i >= 0; i--) {
-                               if (bitVectBitValue(sym->regsUsed,i)) {
+    _G.useWreg = 0;
 
-//                                     fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
-//                                                     __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
-//                                                     pic16_regWithIdx(i)->name);
+    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_poppCodeOp( pic16_popRegFromIdx(i) );
+      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 */
 
-//                                     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
-//                                                     &pic16_pc_preinc1,
-//                                                     PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 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 ));
-               }
+      /* if debug then send end of function */
+/*     if (options.debug && currFunc)  */
+      if (currFunc) {
+        debugFile->writeEndFunction (currFunc, ic, 1);
+      }
        
-               _G.interruptvector = 0;         /* sanity check */
+      if(_G.usefastretfie)
+        pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
+      else
+        pic16_emitpcodeNULLop(POC_RETFIE);
 
-//             pic16_pBlockConvert2ISR(pb);
+      pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
+      
+      _G.usefastretfie = 0;
+      return;
+    }
 
+    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);
-               _G.usefastretfie = 0;
-       } else {
-               if (IFFUNC_ISCRITICAL(sym->type))
-                       pic16_emitcode("setb","ea");
-       
-
-//             pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
-
-               /* 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));
-
-                                       _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));
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -4740,6 +4659,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)
 {
@@ -4907,151 +4827,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)){
@@ -5083,7 +5470,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;
@@ -5095,11 +5482,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 {
@@ -5422,6 +5825,9 @@ check_carry:
   }
 
 }
+#endif
+
+
 
 /*-----------------------------------------------------------------*/
 /* genCmpGt :- greater than comparison                             */
@@ -10020,7 +10426,6 @@ static void genGenPointerGet (operand *left,
 }
 #endif
 
-extern set *externs;
 
 /*-----------------------------------------------------------------*/
 /* genGenPointerGet - gget value from generic pointer space        */
@@ -10478,19 +10883,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++;
        }
@@ -10920,8 +11338,15 @@ 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_gptrreg), 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 */
+    pushaop(AOP(right), 0);
+//    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);
@@ -10953,12 +11378,6 @@ static void genGenPointerSet (operand *right,
         sym = newSymbol( fgptrput, 0 );
         strcpy(sym->rname, fgptrput);
         checkAddSym(&externs, sym);
-
-       sym = newSymbol("__GPTRREG", 0);
-        strcpy(sym->rname, "__GPTRREG");
-        checkAddSym(&externs, sym);
-
-//          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
     }
 
 release:
@@ -11284,16 +11703,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));
@@ -11301,7 +11724,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),
@@ -11365,6 +11788,7 @@ static void genAssign (iCode *ic)
     } else if (AOP_TYPE(right) == AOP_CRY) {
       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
       if(offset == 0) {
+//        debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
        pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
        pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
       }
@@ -11393,6 +11817,9 @@ static void genJumpTab (iCode *ic)
 {
     symbol *jtab;
     char *l;
+    pCodeOp *jt_offs;
+    pCodeOp *jt_offs_hi;
+    pCodeOp *jt_label;
 
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
@@ -11409,6 +11836,7 @@ static void genJumpTab (iCode *ic)
     pic16_emitcode("jmp","@a+dptr");
     pic16_emitcode("","%05d_DS_:",jtab->key+100);
 
+#if 0
     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
     emitSKPNC;
@@ -11416,6 +11844,49 @@ static void genJumpTab (iCode *ic)
     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
     pic16_emitpLabel(jtab->key);
 
+#else
+
+    jt_offs = pic16_popGetTempReg(0);
+    jt_offs_hi = pic16_popGetTempReg(1);
+    jt_label = pic16_popGetLabel (jtab->key);
+    //fprintf (stderr, "Creating jump table...\n");
+
+    // calculate offset into jump table (idx * sizeof (GOTO))
+    pic16_emitpcode(POC_CLRF  , jt_offs_hi);
+    pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
+    pic16_emitpcode(POC_RLCF  , jt_offs_hi);
+    pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
+    pic16_emitpcode(POC_RLCF  , jt_offs_hi);
+    pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
+    pic16_emitpcode(POC_MOVWF , jt_offs);
+
+    // prepare PCLATx (set to first entry in jump table)
+    pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
+    pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
+    pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
+    pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
+    pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
+
+    // set PCLATx to selected entry (new PCL is stored in jt_offs)
+    pic16_emitpcode(POC_ADDWF , jt_offs);
+    pic16_emitpcode(POC_MOVFW , jt_offs_hi);
+    pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
+    emitSKPNC;
+    pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
+
+    // release temporaries and prepare jump into table (new PCL --> WREG)
+    pic16_emitpcode(POC_MOVFW , jt_offs);
+    pic16_popReleaseTempReg (jt_offs_hi, 1);
+    pic16_popReleaseTempReg (jt_offs, 0);
+
+    // jump into the table
+    pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
+
+    // this goto prevents the next label from being removed...
+    pic16_emitpcode(POC_GOTO, jt_label);
+    pic16_emitpLabel(jtab->key);
+
+#endif
     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
 
     /* now generate the jump labels */