* src/SDCCast.c (processParms): disabled W_NONRENT_ARGS for pic16 port
[fw/sdcc] / src / pic16 / gen.c
index 7646de4f02c0bcd0fc4a5d959a6580a29a87c1e3..0a15d8cfcfa4677b287643dc951553b40947dcb6 100644 (file)
@@ -6,7 +6,7 @@
   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
-             -  Vangelis Rokas vrokas@otenet.gr (2003,2004)
+             -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
   
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
@@ -153,7 +153,6 @@ static struct {
     short ipushRegs;
     set *sendSet;
     set *stackRegSet;
-    int interruptvector;
     int usefastretfie;
     bitVect *fregsUsed;
     int stack_lat;                     /* stack offset latency */
@@ -648,11 +647,29 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
     }
 #endif
 
+
+#if 0
+    if(sym->iaccess) {
+      if(space->paged) {
+        fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
+
+        sym->aop = aop = newAsmop (AOP_PAGED);
+        aop->aopu.aop_dir = sym->rname ;
+        aop->size = getSize(sym->type);
+       DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
+       pic16_allocDirReg( IC_LEFT(ic) );
+        return aop;
+      }
+      assert( 0 );
+    }
+#endif
+    
 #if 1
     /* assign depending on the storage class */
     /* if it is on the stack or indirectly addressable */
     /* space we need to assign either r0 or r1 to it   */    
-    if (sym->onStack || sym->iaccess) {
+    if (sym->onStack)  // || sym->iaccess)
+    {
       pCodeOp *pcop[4];
       int i;
       
@@ -704,7 +721,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
            } // if
            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
            pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
-                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
+                           pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
          }
        }
        
@@ -780,7 +797,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
     }
 #endif
 
-#if 0
+#if 1
     /* special case for a function */
     if (IS_FUNC(sym->type)) {   
         sym->aop = aop = newAsmop(AOP_PCODE);
@@ -852,11 +869,15 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
                aop->size = PTRSIZE;
        else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
                aop->size = FPTRSIZE;
-       else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
-       else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
+       else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
+       else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
        else if(sym->onStack) {
                aop->size = PTRSIZE;
         } else {
+          if(SPEC_SCLS(sym->etype) == S_PDATA) {
+            fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
+            aop->size = FPTRSIZE;
+          } else
                assert( 0 );
        }
 
@@ -1069,10 +1090,12 @@ bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
         aop2->type != AOP_REG )
         return FALSE ;
 
+    /* This is a bit too restrictive if one is a subset of the other...
     if (aop1->size != aop2->size )
         return FALSE ;
+    */
 
-    for (i = 0 ; i < aop1->size ; i++ ) {
+    for (i = 0 ; i < min(aop1->size, aop2->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)
@@ -1170,6 +1193,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
     b) has a spill location */
     if (sym->isspilt || sym->nRegs == 0) {
 
+//      debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs);
       DEBUGpic16_emitcode(";","%d",__LINE__);
         /* rematerialize it NOW */
         if (sym->remat) {
@@ -1230,9 +1254,16 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
 
        sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
        //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
-       aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
-                                         getSize(sym->type), 
-                                         sym->usl.spillLoc->offset, op);
+       if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
+         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
+                                                 getSize(sym->type), 
+                                                 sym->usl.spillLoc->offset, op);
+       } else {
+         fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
+         DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
+         assert (getSize(sym->type) <= 1);
+         aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
+       }
         aop->size = getSize(sym->type);
 
         return;
@@ -1335,7 +1366,7 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
                  /* initialise for stack access via frame pointer */
                  pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
                  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
-                        aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
+                        aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
                }
        
                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
@@ -1543,6 +1574,21 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
       strcpy(rs,s);   
       return rs;
 
+#if 0
+    case AOP_PAGED:
+      DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
+      if (offset) {
+       sprintf(s,"(%s + %d)",
+               aop->aopu.aop_dir,
+               offset);
+      } else
+           sprintf(s,"%s",aop->aopu.aop_dir);
+      DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
+      rs = Safe_calloc(1,strlen(s)+1);
+      strcpy(rs,s);   
+      return rs;
+#endif
+
     case AOP_STA:
         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
         return (rs);
@@ -1941,6 +1987,12 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
        
+#if 0
+    case AOP_PAGED:
+      DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
+      return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
+#endif
+
     case AOP_REG:
       {
        int rIdx;
@@ -1998,16 +2050,14 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
                          __LINE__, 
                          ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
-#if 1
-       switch( aop->aopu.pcop->type ) {
-               case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
-               case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
-               default:
-                       assert( 0 );    /* should never reach here */;
-       }
-#else
-      PCOI(pcop)->offset = offset;
-#endif
+      switch( aop->aopu.pcop->type ) {
+        case PO_DIR: PCOR(pcop)->instance += offset; break;
+        case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
+        case PO_WREG: assert (offset==0); break;
+        default:
+         fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
+          assert( 0 ); /* should never reach here */;
+      }
       return pcop;
     }
 
@@ -2304,7 +2354,7 @@ void pic16_testStackOverflow(void)
 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_stack_postdec )));   //&pic16_pc_postdec1)));
   if(pic16_options.gstack)
     pic16_testStackOverflow();
     
@@ -2313,7 +2363,7 @@ void pic16_pushpCodeOp(pCodeOp *pcop)
 /* 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_stack_preinc ), pcop));
   if(pic16_options.gstack)
     pic16_testStackOverflow();
 }
@@ -2325,7 +2375,7 @@ void pic16_poppCodeOp(pCodeOp *pcop)
 void pushw(void)
 {
   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-  pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
+  pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1));
   if(pic16_options.gstack)
     pic16_testStackOverflow();
 }
@@ -2340,13 +2390,12 @@ void pushaop(asmop *aop, int offset)
 
   if(is_LitAOp(aop)) {
     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
-    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));       //&pic16_pc_postdec1));
   } else {
     pic16_emitpcode(POC_MOVFF,
-      pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
+      pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));     //&pic16_pc_postdec1)));
   }
 
-//  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
   if(pic16_options.gstack)
     pic16_testStackOverflow();
 }
@@ -2357,7 +2406,7 @@ 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));
+  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
   if(pic16_options.gstack)
     pic16_testStackOverflow();
 }
@@ -2371,7 +2420,7 @@ void popaopidx(asmop *aop, int offset, int index)
     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_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
     if(pic16_options.gstack)
       pic16_testStackOverflow();
 }
@@ -2685,6 +2734,8 @@ static void genUminus (iCode *ic)
 {
   int size, i;
   sym_link *optype, *rtype;
+  symbol *label;
+  int needLabel=0;
 
     FENTRY;    
     
@@ -2713,21 +2764,33 @@ static void genUminus (iCode *ic)
 
     /* otherwise subtract from zero by taking the 2's complement */
     size = AOP_SIZE(IC_LEFT(ic));
-
-    for(i=0; i<size; i++) {
-      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
-        pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
-      else {
-        pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
-        pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
-      }
-    }
-
-    pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
-    for(i=1; i<size; i++) {
-      emitSKPNZ;
-      pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
+    label = newiTempLabel ( NULL );
+    
+    if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+      for (i=size-1; i > 0; i--) {
+        pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
+      } // for
+      pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
+      for (i=1; i < size; i++) {
+        if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
+        pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
+      } // for
+    } else {
+      for (i=size-1; i >= 0; i--) {
+        pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
+       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
+      } // for
+      if (size > 1) {
+        for (i=0; i < size-2; i++) {
+          pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
+          pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
+       } // for
+        pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
+      } // if
+      pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
     }
+    if (needLabel)
+      pic16_emitpLabel (label->key);
 
 release:
     /* release the aops */
@@ -2925,10 +2988,10 @@ static void assignResultValue(operand * oper, int rescall)
                        
        /* fix stack */
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
-       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
+       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
        if(STACK_MODEL_LARGE) {
          emitSKPNC;
-         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
+         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
        }
       }                        
     } else {
@@ -3177,7 +3240,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);
+    inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
 
 #if 0
     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
@@ -3293,14 +3356,14 @@ static void genCall (iCode *ic)
     
     if(stackParms>0) {
       if(stackParms == 1) {
-        pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
+        pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));       //&pic16_pc_fsr1l));
       } else {
         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
-        pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
+        pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));     //&pic16_pc_fsr1l ));
       }
       if(STACK_MODEL_LARGE) {
         emitSKPNC;
-        pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
+        pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));      //&pic16_pc_fsr1h ));
       }
     }
 
@@ -3381,6 +3444,11 @@ static void genPcall (iCode *ic)
     // push return address
     // push $ on return stack, then replace with retlbl
 
+    /* Thanks to Thorsten Klose for pointing out that the following
+     * snippet should be interrupt safe */
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
+    pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
+
     pic16_emitpcodeNULLop(POC_PUSH);
 
     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
@@ -3390,6 +3458,11 @@ static void genPcall (iCode *ic)
     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
 
+
+    /* restore interrupt control register */
+    pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
+
     /* 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)));
@@ -3427,11 +3500,10 @@ static void genPcall (iCode *ic)
     
     if(stackParms>0) {
       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
+      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
       if(STACK_MODEL_LARGE) {
-        /* this implies that stackParms < 256 !!! -- VR */
         emitSKPNC;
-        pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
+        pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
       }
     }
 }
@@ -3509,6 +3581,10 @@ static void genFunction (iCode *ic)
       char asymname[128];
       pBlock *apb;
 
+
+//        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
+
+#if 0
         {
           int i, found=-1;
 
@@ -3524,12 +3600,16 @@ static void genFunction (iCode *ic)
             if(found == -1) {
               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
                             __FILE__, __LINE__, sym->name);
-              assert( 0 );
+//              assert( 0 );
             }
             _G.interruptvector = found;
         }
+#endif
 
-        sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
+        if(FUNC_INTNO(sym->type) == 256)
+          sprintf(asymname, "ivec_%s", sym->name);
+        else
+          sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
         asym = newSymbol(asymname, 0);
 
         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
@@ -3548,14 +3628,18 @@ static void genFunction (iCode *ic)
            abSym = Safe_calloc(1, sizeof(absSym));
            strcpy(abSym->name, asymname);
 
-           switch( _G.interruptvector ) {
+           switch( FUNC_INTNO(sym->type) ) {
              case 0: abSym->address = 0x000000; break;
               case 1: abSym->address = 0x000008; break;
               case 2: abSym->address = 0x000018; break;
+              
+              default:
+                abSym->address = -1; break;
             }
 
             /* relocate interrupt vectors if needed */
-            abSym->address += pic16_options.ivt_loc;
+            if(abSym->address != -1)
+              abSym->address += pic16_options.ivt_loc;
 
             addSet(&absSymSet, abSym);
         }
@@ -3600,7 +3684,7 @@ static void genFunction (iCode *ic)
         _G.usefastretfie = 1;  /* use shadow registers by default */
         
         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
-        if(!(_G.interruptvector == 1)) {
+        if(!FUNC_ISSHADOWREGS(sym->type)) {
           /* do not save WREG,STATUS,BSR for high priority interrupts
            * because they are stored in the hardware shadow registers already */
           _G.usefastretfie = 0;
@@ -3628,12 +3712,12 @@ static void genFunction (iCode *ic)
       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));
+          pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
+        pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
+
+        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
         if(STACK_MODEL_LARGE)
-          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
+          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
       }
     }
 
@@ -3643,12 +3727,12 @@ static void genFunction (iCode *ic)
       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
 
       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
-      pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
+      pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));       //&pic16_pc_fsr1l));
       emitSKPC;
-      pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
+      pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));                //&pic16_pc_fsr1h));
     }
           
-    if(inWparamList(sym->name)) {
+    if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
         _G.useWreg = 0;
       else
@@ -3733,17 +3817,17 @@ static void genEndFunction (iCode *ic)
     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
           && sym->stack) {
       if (sym->stack == 1) {
-        pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l));
-        pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
+        pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
+        pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
       } else {
         // we have to add more than one...
-        pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value!
+        pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));   // this holds a return value!
         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
-        pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
+        pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
         emitSKPNC;
-        pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
+        pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
-        pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value!
+        pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
       }
     }
 
@@ -3751,10 +3835,8 @@ static void genEndFunction (iCode *ic)
       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));
+          pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
+        pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
       }
     }
 
@@ -3766,14 +3848,14 @@ static void genEndFunction (iCode *ic)
       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
 
-      if(!(_G.interruptvector == 1)) {
+      if(!FUNC_ISSHADOWREGS(sym->type)) {
         /* 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 */
+//      _G.interruptvector = 0;                /* sanity check */
 
 
       /* if debug then send end of function */
@@ -3815,8 +3897,25 @@ static void genEndFunction (iCode *ic)
 
 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
 {
-  if(is_LitOp(op)) {
-    unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
+  unsigned long lit=1;
+  // this fails for is_LitOp(op) (if op is an AOP_PCODE)
+  if(AOP_TYPE(op) == AOP_LIT) {
+    if(!IS_FLOAT(operandType( op ))) {
+      lit = (unsigned long)floatFromVal(AOP(op)->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(op)->aopu.aop_lit);
+      lit = info.lit_int;
+    }
+  }
+
+  if (is_LitOp(op)) {
       if(lit == 0) {
         pic16_emitpcode(POC_CLRF, dest);
       } else {
@@ -3889,13 +3988,13 @@ static void genRet (iCode *ic)
                        
                /* setup FSR0 */
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
-                       pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
+                       pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
 
                if(STACK_MODEL_LARGE) {
                        pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
-                               pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
+                               pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
                } else {
-                       pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
+                       pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
                }
        }
                                
@@ -4577,6 +4676,33 @@ static void genIfxJump (iCode *ic, char *jval)
     ic->generated = 1;
 }
 
+static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
+{
+  FENTRY;
+  
+    /* if true label then we jump if condition
+    supplied is true */
+    if ( IC_TRUE(ic) ) {
+      DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);    
+      pic16_emitpcode(POC_BTFSC, jop);
+
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
+      pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
+
+    } else {
+      /* false label is present */
+      DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
+      pic16_emitpcode(POC_BTFSS, jop);
+         
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
+      pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
+    }
+
+
+    /* mark the icode as generated */
+    ic->generated = 1;
+}
+
 #if 0
 // not needed ATM
 
@@ -4748,7 +4874,9 @@ static int genChkZeroes(operand *op, int lit,  int size)
 }
 #endif
 
+#if !defined(__BORLANDC__) && !defined(_MSC_VER)
 #define DEBUGpc(fmt,...)  DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#endif
 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA)
 
@@ -4831,7 +4959,9 @@ static void genCmp (operand *left,operand *right,
    * make sure that left is register (or the like) *
    *************************************************/
   if (!isAOP_REGlike(left)) {
+    #if !defined(__BORLANDC__) && !defined(_MSC_VER)
     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
+    #endif
     assert (isAOP_LIT(left));
     assert (isAOP_REGlike(right));
     // swap left and right
@@ -4867,7 +4997,9 @@ static void genCmp (operand *left,operand *right,
   if (isAOP_LIT(right)) {
     if (!sign) {
       // unsigned comparison to a literal
+      #if !defined(__BORLANDC__) && !defined(_MSC_VER)
       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
+      #endif
       if (lit == 0) {
        // unsigned left < 0? always false
        if (performedLt) emitCLRC; else emitSETC;
@@ -4875,7 +5007,9 @@ static void genCmp (operand *left,operand *right,
       }
     } else {
       // signed comparison to a literal
+      #if !defined(__BORLANDC__) && !defined(_MSC_VER)
       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
+      #endif
       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
        // signed left < 0x80000000? always false
        if (performedLt) emitCLRC; else emitSETC;
@@ -10985,10 +11119,54 @@ static void genNearPointerGet (operand *left,
     }
     
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    pic16_aopOp (result,ic,FALSE);
+    
+    DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
+
+#if 1
+    if(IS_BITFIELD( retype )
+      && (SPEC_BLEN(operandType(result))==1)
+    ) {
+      iCode *nextic;
+      pCodeOp *jop;
+      int bitstrt, bytestrt;
+
+        /* if this is bitfield of size 1, see if we are checking the value
+         * of a single bit in an if-statement,
+         * if yes, then don't generate usual code, but execute the
+         * genIfx directly -- VR */
+
+        nextic = ic->next;
+
+        /* CHECK: if next iCode is IFX
+         * and current result operand is nextic's conditional operand
+         * and current result operand live ranges ends at nextic's key number
+         */
+        if((nextic->op == IFX)
+          && (result == IC_COND(nextic))
+          && (OP_LIVETO(result) == nextic->seq)
+          ) {
+            /* everything is ok then */
+            /* find a way to optimize the genIfx iCode */
+
+            bytestrt = SPEC_BSTR(operandType(result))/8;
+            bitstrt = SPEC_BSTR(operandType(result))%8;
+            
+            jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
+
+            genIfxpCOpJump(nextic, jop);
+            
+            pic16_freeAsmop(left, NULL, ic, TRUE);
+            pic16_freeAsmop(result, NULL, ic, TRUE);
+            return;
+        }
+    }
+#endif
+
 
     /* if the value is already in a pointer register
      * then don't need anything more */
-    if (!AOP_INPREG(AOP(left))) {
+    if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
       /* otherwise get a free pointer register */
       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
                
@@ -11005,12 +11183,6 @@ static void genNearPointerGet (operand *left,
         }
       }
     }
-//    else
-//    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
-    
-    pic16_aopOp (result,ic,FALSE);
-    
-    DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
 
     /* if bitfield then unpack the bits */
     if (IS_BITFIELD(retype)) 
@@ -11216,6 +11388,7 @@ static void genFarPointerGet (operand *left,
 
     pic16_freeAsmop(result,NULL,ic,TRUE);
 }
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* genCodePointerGet - get value from code space                  */
@@ -11268,6 +11441,7 @@ static void genCodePointerGet (operand *left,
     pic16_freeAsmop(result,NULL,ic,TRUE);
 }
 #endif
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* genGenPointerGet - gget value from generic pointer space        */
@@ -11436,29 +11610,11 @@ static void genConstPointerGet (operand *left,
   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
 
   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
-#if 0                                                                  // patch 15
-  pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
-  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
-  pic16_emitpLabel(albl->key);
-
-  poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
-  
-  /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
-  pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
-  pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
-  pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
-  pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
-
-  pic16_emitpLabel(blbl->key);
-
-  pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
-#endif                                                                 // patch 15
-
 
   // set up table pointer
   if( (AOP_TYPE(left) == AOP_PCODE) 
       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
-          || (AOP(left)->aopu.pcop->type == PO_DIR)))                  // patch 15 ......
+          || (AOP(left)->aopu.pcop->type == PO_DIR)))
     {
       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
@@ -11466,25 +11622,20 @@ static void genConstPointerGet (operand *left,
       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
-    }
-  else
-    {
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
-    }
-
+  } else {
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
+  }
 
-  while(size--)
-    {
-      pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
-      offset++;
-    }
+  while(size--) {
+    pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
+    offset++;
+  }
     
   pic16_freeAsmop(left,NULL,ic,TRUE);
   pic16_freeAsmop(result,NULL,ic,TRUE);
-
 }
 
 
@@ -11493,9 +11644,9 @@ static void genConstPointerGet (operand *left,
 /*-----------------------------------------------------------------*/
 static void genPointerGet (iCode *ic)
 {
-    operand *left, *result ;
-    sym_link *type, *etype;
-    int p_type;
+  operand *left, *result ;
+  sym_link *type, *etype;
+  int p_type;
 
     FENTRY;
     
@@ -11516,57 +11667,56 @@ static void genPointerGet (iCode *ic)
 
     /* if left is of type of pointer then it is simple */
     if (IS_PTR(type) && !IS_FUNC(type->next)) 
-        p_type = DCL_TYPE(type);
+      p_type = DCL_TYPE(type);
     else {
-       /* we have to go by the storage class */
-       p_type = PTR_TYPE(SPEC_OCLS(etype));
+      /* we have to go by the storage class */
+      p_type = PTR_TYPE(SPEC_OCLS(etype));
 
-       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
+      DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
 
-       if (SPEC_OCLS(etype)->codesp ) {
-         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
-         //p_type = CPOINTER ; 
-       }
-       else
-           if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
-             DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
-              /*p_type = FPOINTER ;*/ 
-           else
-               if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
-                 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
-/*                 p_type = PPOINTER; */
-               else
-                   if (SPEC_OCLS(etype) == idata )
-                     DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
-/*                     p_type = IPOINTER; */
-                   else
-                     DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
-/*                     p_type = POINTER ; */
+      if (SPEC_OCLS(etype)->codesp ) {
+        DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
+        //p_type = CPOINTER ;  
+      } else
+      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
+        DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
+        /*p_type = FPOINTER ;*/ 
+      } else
+      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
+        DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
+        /* p_type = PPOINTER; */
+      } else
+      if (SPEC_OCLS(etype) == idata ) {
+        DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
+        /* p_type = IPOINTER; */
+      } else {
+        DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
+        /* p_type = POINTER ; */
+      }
     }
 
     /* now that we have the pointer type we assign
     the pointer values */
     switch (p_type) {
-
-    case POINTER:      
-    case IPOINTER:
+      case POINTER:    
+      case IPOINTER:
        genNearPointerGet (left,result,ic);
        break;
 
-    case PPOINTER:
+      case PPOINTER:
        genPagedPointerGet(left,result,ic);
        break;
 
-    case FPOINTER:
+      case FPOINTER:
        genFarPointerGet (left,result,ic);
        break;
 
-    case CPOINTER:
+      case CPOINTER:
        genConstPointerGet (left,result,ic);
        //pic16_emitcodePointerGet (left,result,ic);
        break;
 
-    case GPOINTER:
+      case GPOINTER:
 #if 0
       if (IS_PTR_CONST(type))
        genConstPointerGet (left,result,ic);
@@ -11580,7 +11730,6 @@ static void genPointerGet (iCode *ic)
              "genPointerGet: illegal pointer type");
     
     }
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -11668,39 +11817,106 @@ static void genPackBits (sym_link    *etype , operand *result,
         } else
           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
 
-       /* if the bit lenth is less than or    */
+       /* if the bit length is less than or   */
        /* it exactly fits a byte then         */
        if((shCnt=SPEC_BSTR(etype))
                || SPEC_BLEN(etype) <= 8 )  {
+               int fsr0_setup = 0;
 
-               pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
+               if (blen != 8 || bstr != 0) {
+                 // we need to combine the value with the old value
+                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
 
-               /* shift left acc */
-               AccLsh(shCnt);
+                 /* shift left acc */
+                 AccLsh(shCnt);
 
-               /* using PRODL as a temporary register here */
-               pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
+                 /* using PRODH as a temporary register here */
+                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
 
-               switch (p_type) {
+                 /* get old value */
+                 switch (p_type) {
                        case FPOINTER:
                        case POINTER:
                                pic16_loadFSR0( result );
+                               fsr0_setup = 1;
                                pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
 //                             pic16_emitcode ("mov","b,a");
 //                             pic16_emitcode("mov","a,@%s",rname);
                                break;
 
                        case GPOINTER:
-                                werror(W_POSSBUG2, __FILE__, __LINE__);
+                               if (AOP(result)->aopu.aop_reg[2]) {
+                                 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
+                                 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_prodl)));
+                                 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
+                                 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1"));
+                                 {
+                                   symbol *sym;
+                                   sym = newSymbol( "__gptrget1", 0 );
+                                   strcpy(sym->rname, "__gptrget1");
+                                   checkAddSym(&externs, sym);
+                                 }
+                               } else {
+                                 // data pointer (just 2 byte given)
+                                 pic16_loadFSR0( result );
+                                 fsr0_setup = 1;
+                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
+                               }
+                               
+                               // warnings will be emitted below
+                               //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
+                                //werror(W_POSSBUG2, __FILE__, __LINE__);
                                break;
 
-               }
+                       default:
+                               assert (0 && "invalid pointer type specified");
+                               break;
+                 }
 #if 1
-               pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
+                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
                        (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
                                        (unsigned char)(0xff >> (8-bstr))) ));
-               pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
-               pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
+               } // if (blen != 8 || bstr != 0)
+
+               /* write new value back */
+               switch (p_type) {
+                       case FPOINTER:
+                       case POINTER:
+                               if (!fsr0_setup) pic16_loadFSR0( result );
+                               pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+                               break;
+
+                       case GPOINTER:
+                               if (AOP(result)->aopu.aop_reg[2]) {
+                                 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
+                                 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
+                                 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_prodl)));
+                                 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
+                                 pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1"));
+                                 {
+                                   symbol *sym;
+                                   sym = newSymbol( "__gptrput1", 0 );
+                                   strcpy(sym->rname, "__gptrput1");
+                                   checkAddSym(&externs, sym);
+                                 }
+                               } else {
+                                 // data pointer (just 2 byte given)
+                                 if (!fsr0_setup) pic16_loadFSR0( result );
+                                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+                               }
+                               
+                               // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
+                               //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
+                                werror(W_POSSBUG2, __FILE__, __LINE__);
+                               break;
+
+                       default:
+                               assert (0 && "invalid pointer type specified");
+                               break;
+               }
 #endif
 
          return;
@@ -11904,7 +12120,7 @@ static void genNearPointerSet (operand *right,
 
        /* if the value is already in a pointer register
         * then don't need anything more */
-       if (!AOP_INPREG(AOP(result))) {
+       if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
                /* otherwise get a free pointer register */
                DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
@@ -11948,24 +12164,24 @@ static void genNearPointerSet (operand *right,
                                pic16_emitcode("movf","indf0,w ;1");
                        } else {
 
-                               if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
-                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
-                                       if (size) {                                                                     // 
-                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
-                                       } else {                                                                        // 
-                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
-                                       }                                                                               // 
-                               } else { // no literal                                                                  // 
-                                       if(size) {                                                                      // 
-                                               pic16_emitpcode(POC_MOVFF,                                              // 
-                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
-                                                                       pic16_popCopyReg(&pic16_pc_postinc0)));         // 
-                                       } else {                                                                        // 
-                                               pic16_emitpcode(POC_MOVFF,                                              // 
-                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
-                                                                       pic16_popCopyReg(&pic16_pc_indf0)));            //
-                                       }                                                                               //
-                               }                                                                                       // patch 10
+                               if (AOP_TYPE(right) == AOP_LIT) {
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
+                                       if (size) {
+                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
+                                       } else {
+                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
+                                       }
+                               } else { // no literal
+                                       if(size) {
+                                               pic16_emitpcode(POC_MOVFF,
+                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),
+                                                                       pic16_popCopyReg(&pic16_pc_postinc0)));
+                                       } else {
+                                               pic16_emitpcode(POC_MOVFF,
+                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),
+                                                                       pic16_popCopyReg(&pic16_pc_indf0)));
+                                       }
+                               }
                        }
                        offset++;
                }
@@ -12381,27 +12597,26 @@ static void genPointerSet (iCode *ic)
     /* now that we have the pointer type we assign
     the pointer values */
     switch (p_type) {
+      case POINTER:
+      case IPOINTER:
+        genNearPointerSet (right,result,ic);
+        break;
 
-    case POINTER:
-    case IPOINTER:
-       genNearPointerSet (right,result,ic);
-       break;
-
-    case PPOINTER:
-       genPagedPointerSet (right,result,ic);
-       break;
-
-    case FPOINTER:
-       genFarPointerSet (right,result,ic);
+      case PPOINTER:
+        genPagedPointerSet (right,result,ic);
        break;
 
-    case GPOINTER:
-       genGenPointerSet (right,result,ic);
-       break;
+      case FPOINTER:
+        genFarPointerSet (right,result,ic);
+        break;
+        
+      case GPOINTER:
+        genGenPointerSet (right,result,ic);
+        break;
 
-    default:
-      werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
-             "genPointerSet: illegal pointer type");
+      default:
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+          "genPointerSet: illegal pointer type");
     }
 }
 
@@ -12478,10 +12693,10 @@ static void genAddrOf (iCode *ic)
        } // if
        DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
        pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
-       pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(&pic16_pc_fsr2l));
+       pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
        pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
        pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
-       pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(&pic16_pc_fsr2h));
+       pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
        pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
       }
 
@@ -12496,10 +12711,6 @@ static void genAddrOf (iCode *ic)
     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
     size = AOP_SIZE(IC_RESULT(ic));
 
-
-    /* Assume that what we want the address of is in data space
-     * since there is no stack on the PIC, yet! -- VR */
-  
     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
@@ -12693,7 +12904,7 @@ static void genAssign (iCode *ic)
                                pic16_popCopyReg(&pic16_pc_tblptru)));
        }
 
-       size = min(AOP_SIZE(right), AOP_SIZE(result));
+       size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
        while(size--) {
                pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
@@ -12701,8 +12912,9 @@ static void genAssign (iCode *ic)
                offset++;
        }
 
-       if(AOP_SIZE(result) > AOP_SIZE(right)) {
-               size = AOP_SIZE(result) - AOP_SIZE(right);
+       size = getSize(OP_SYM_ETYPE(right));
+       if(AOP_SIZE(result) > size) {
+               size = AOP_SIZE(result) - size;
                while(size--) {
                        pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
                        offset++;
@@ -13237,7 +13449,13 @@ static void genCast (iCode *ic)
                break;
 
             case GPOINTER:
-              pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
+               if (GPTRSIZE > AOP_SIZE(right)) {
+                 // assume data pointer... THIS MIGHT BE WRONG!
+                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
+                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
+               } else {
+                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
+               }
               break;
               
            default:
@@ -13433,10 +13651,26 @@ static void genReceive (iCode *ic)
 static void
 genDummyRead (iCode * ic)
 {
-  pic16_emitcode ("; genDummyRead","");
-  pic16_emitcode ("; not implemented","");
+  operand *op;
+  int i;
 
-  ic = ic;
+  op = IC_RIGHT(ic);
+  if (op && IS_SYMOP(op)) {
+    if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
+      fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
+      return;
+    }
+    pic16_aopOp (op, ic, FALSE);
+    for (i=0; i < AOP_SIZE(op); i++) {
+      // may need to protect this from the peepholer -- this is not nice but works...
+      pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
+      pic16_mov2w (AOP(op),i);
+      pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
+    } // for i
+    pic16_freeAsmop (op, NULL, ic, TRUE);
+  } else if (op) {
+    fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
+  } // if
 }
 
 /*-----------------------------------------------------------------*/
@@ -13472,7 +13706,7 @@ void genpic16Code (iCode *lic)
 
     for (ic = lic ; ic ; ic = ic->next ) {
 
-      DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
+      DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
       if ( cln != ic->lineno ) {
         if ( options.debug ) {
           debugFile->writeCLine (ic);