* device/include/pic16/string.h: modified prototype for memccpy()
[fw/sdcc] / src / pic16 / gen.c
index fc6eb6f85420df6f758d1433c2dc0b9f7b51fe4d..31b932c50825f93d7c45cf62e97154658ba6dfc3 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;
       
@@ -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) {
 
+//      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
       DEBUGpic16_emitcode(";","%d",__LINE__);
         /* rematerialize it NOW */
         if (sym->remat) {
@@ -1196,7 +1220,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
 #endif
 
 #if 1
-        if (sym->ruonly ) {
+        if (sym->ruonly) {
          /*
          sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
          aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
@@ -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;
@@ -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;
@@ -1959,7 +2011,7 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
        PCOR(pcop)->instance = offset;
        pcop->type = PCOR(pcop)->r->pc_type;
        
-       DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
+       DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
        rs = aop->aopu.aop_reg[offset]->name;
        DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
        return pcop;
@@ -2001,7 +2053,11 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
       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;
@@ -2680,6 +2736,8 @@ static void genUminus (iCode *ic)
 {
   int size, i;
   sym_link *optype, *rtype;
+  symbol *label;
+  int needLabel=0;
 
     FENTRY;    
     
@@ -2708,21 +2766,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 */
@@ -3172,7 +3242,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 );
@@ -3376,6 +3446,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));
@@ -3385,6 +3460,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)));
@@ -3503,6 +3583,9 @@ 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;
 
@@ -3518,12 +3601,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"));
@@ -3542,14 +3629,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);
         }
@@ -3594,7 +3685,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;
@@ -3616,10 +3707,10 @@ static void genFunction (iCode *ic)
 
     /* 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(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
+      if(0 || !options.ommitFramePtr || sym->regsUsed) {
         /* setup the stack frame */
         if(STACK_MODEL_LARGE)
           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
@@ -3642,7 +3733,7 @@ static void genFunction (iCode *ic)
       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
@@ -3742,7 +3833,7 @@ static void genEndFunction (iCode *ic)
     }
 
     if(strcmp(sym->name, "main")) {
-      if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
+      if(0 || !options.ommitFramePtr || sym->regsUsed) {
         /* restore stack frame */
         if(STACK_MODEL_LARGE)
           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
@@ -3758,14 +3849,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 */
@@ -3807,8 +3898,25 @@ static void genEndFunction (iCode *ic)
 
 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
 {
+  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)) {
-    unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
       if(lit == 0) {
         pic16_emitpcode(POC_CLRF, dest);
       } else {
@@ -6967,6 +7075,7 @@ static void genCmpEq (iCode *ic, iCode *ifx)
   int preserve_result = 0;
   int generate_result = 0;
   int i=0;
+  unsigned long lit = -1;
 
   FENTRY;
   
@@ -6991,6 +7100,10 @@ static void genCmpEq (iCode *ic, iCode *ifx)
       left = tmp;
     }
 
+  if (AOP_TYPE(right) == AOP_LIT) {
+    lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
+  }
+
   if ( regsInCommon(left, result) || regsInCommon(right, result) )
     preserve_result = 1;
 
@@ -7012,9 +7125,11 @@ static void genCmpEq (iCode *ic, iCode *ifx)
           else
             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
         }
-      if(is_LitOp(right))
-        pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
-      else
+      if(is_LitOp(right)) {
+        if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
+          pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
+        }
+      } else
         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
 
       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
@@ -8519,8 +8634,13 @@ static void genInline (iCode *ic)
        buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
        strcpy(buffer,IC_INLINE(ic));
 
-//     fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
-
+       while((bp1=strstr(bp, "\\n"))) {
+         *bp1++ = '\n';
+         *bp1++ = ' ';
+         bp = bp1;
+        }
+        bp = bp1 = buffer;
+        
        /* emit each line as a code */
        while (*bp) {
                if (*bp == '\n') {
@@ -10741,9 +10861,16 @@ static void genRightShift (iCode *ic) {
 #endif
 
 
-void pic16_loadFSR0(operand *op)
+/* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
+void pic16_loadFSR0(operand *op, int lit)
 {
-       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+  if(is_LitOp( op ) || lit) {
+    pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+  } else {
+    // set up FSR0 with address of result
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -10796,7 +10923,7 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp
         /* the following call to pic16_loadFSR0 is temporary until
          * optimization to handle single bit assignments is added
          * to the function. Until then use the old safe way! -- VR */
-        pic16_loadFSR0( left );
+        pic16_loadFSR0( left, 1 );
  
        /* read the first byte  */
        switch (ptype) {
@@ -10982,7 +11109,7 @@ static void genNearPointerGet (operand *left,
                               operand *result, 
                               iCode *ic)
 {
-  asmop *aop = NULL;
+//  asmop *aop = NULL;
   //regs *preg = NULL ;
   sym_link *rtype, *retype;
   sym_link *ltype = operandType(left);    
@@ -11059,22 +11186,11 @@ static void genNearPointerGet (operand *left,
 
     /* 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__);
                
-      /* VR -- the whole concept is to load FSR0 with the address of the symbol */
-      /* bitfields will be handled by genUnpackBits */
-      if(!IS_BITFIELD(retype)) {
-
-        if(is_LitAOp( AOP(left) )) {
-          pic16_loadFSR0( left );
-        } else {
-            // set up FSR0 with address from left
-            pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
-            pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
-        }
-      }
+      ;
     }
 
     /* if bitfield then unpack the bits */
@@ -11087,11 +11203,8 @@ static void genNearPointerGet (operand *left,
        
       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-      /* fsr0 is loaded already -- VR */
-//      pic16_loadFSR0( left );
+      pic16_loadFSR0( left, 0 );
 
-//      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
-//      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
       while(size--) {
         if(size) {
           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
@@ -11101,29 +11214,9 @@ static void genNearPointerGet (operand *left,
                 pic16_popGet(AOP(result), offset++)));
         }
       }
-#if 0
-//      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
-//      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
-      if(size)
-        pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
-#endif
-/*
-       while (size--) {
-           if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
-
-               pic16_emitcode("mov","a,@%s",rname);
-               pic16_aopPut(AOP(result),"a",offset);
-           } else {
-               sprintf(buffer,"@%s",rname);
-               pic16_aopPut(AOP(result),buffer,offset);
-           }
-           offset++ ;
-           if (size)
-               pic16_emitcode("inc","%s",rname);
-       }
-*/
     }
 
+#if 0
     /* now some housekeeping stuff */
     if (aop) {
       /* we had to allocate for this iCode */
@@ -11145,6 +11238,7 @@ static void genNearPointerGet (operand *left,
 //          pic16_emitcode("dec","%s",rname);
        }
     }
+#endif
 
     /* done */
     pic16_freeAsmop(left,NULL,ic,TRUE);
@@ -11376,7 +11470,7 @@ static void genGenPointerGet (operand *left,
                // set up FSR0 with address from left
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
-
+                
                offset = 0 ;
 
                while(size--) {
@@ -11464,6 +11558,7 @@ static void genGenPointerGet (operand *left,
         symbol *sym;
 
           sym = newSymbol( fgptrget, 0 );
+          sym->used++;
           strcpy(sym->rname, fgptrget);
           checkAddSym(&externs, sym);
 
@@ -11637,7 +11732,6 @@ static void genPackBits (sym_link    *etype , operand *result,
   int rLen = 0 ;
   int blen, bstr ;   
   sym_link *retype;
-  char *l ;
 
        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        blen = SPEC_BLEN(etype);
@@ -11664,7 +11758,7 @@ static void genPackBits (sym_link    *etype , operand *result,
                                                pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
                                }
                        } else {
-                                pic16_loadFSR0( result );
+                                pic16_loadFSR0(result, 1);
                                if(lit) {
                                        pic16_emitpcode(POC_BSF,
                                                pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
@@ -11676,7 +11770,7 @@ static void genPackBits (sym_link    *etype , operand *result,
        
                  return;
                }
-
+                /* move literal to W */
                pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
                offset++;
        } else
@@ -11707,80 +11801,144 @@ static void genPackBits (sym_link    *etype , operand *result,
             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
             
             return;
-        } else
+        } else {
+          /* move right to W */
           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);
+         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
+               SPEC_BSTR(etype), SPEC_BLEN(etype));
+               
+                 /* 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 );
+                               pic16_loadFSR0( result, 1 );
+                               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, 1 );
+                                 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, 1 );
+                               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, 1 );
+                                 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;
        }
 
 
+#if 0
        fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
        fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
        exit(-1);
+#endif
 
 
-    /* if we r done */
-    if ( SPEC_BLEN(etype) <= 8 )
-        return ;
-
-    pic16_emitcode("inc","%s",rname);
-    rLen = SPEC_BLEN(etype) ;     
-
-
-
+    pic16_loadFSR0(result, 1);                 // load FSR0 with address of result
+    rLen = SPEC_BLEN(etype)-8;
+    
     /* now generate for lengths greater than one byte */
     while (1) {
-
-        l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
-
         rLen -= 8 ;
-        if (rLen <= 0 )
-            break ;
+        if (rLen <= 0 ) {
+          mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
+          break ;
+        }
 
         switch (p_type) {
             case POINTER:
-                if (*l == '@') {
-                    MOVA(l);
-                    pic16_emitcode("mov","@%s,a",rname);
-                } else
-                    pic16_emitcode("mov","@%s,%s",rname,l);
+                  pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
                 break;
 
+/*
             case FPOINTER:
                 MOVA(l);
                 pic16_emitcode("movx","@dptr,a");
@@ -11790,21 +11948,25 @@ static void genPackBits (sym_link    *etype , operand *result,
                 MOVA(l);
                 DEBUGpic16_emitcode(";lcall","__gptrput");
                 break;  
+*/
+          default:
+            assert(0);
         }   
-        pic16_emitcode ("inc","%s",rname);
-    }
 
-    MOVA(l);
+
+        pic16_mov2w(AOP(right), offset++);
+    }
 
     /* last last was not complete */
     if (rLen)   {
         /* save the byte & read byte */
         switch (p_type) {
             case POINTER:
-                pic16_emitcode ("mov","b,a");
-                pic16_emitcode("mov","a,@%s",rname);
+//                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
+                pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
                 break;
 
+/*
             case FPOINTER:
                 pic16_emitcode ("mov","b,a");
                 pic16_emitcode("movx","a,@dptr");
@@ -11816,29 +11978,40 @@ static void genPackBits (sym_link    *etype , operand *result,
                 pic16_emitcode ("lcall","__gptrget");
                 pic16_emitcode ("pop","b");
                 break;
+*/
+            default:
+              assert(0);
         }
-
-        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
-        pic16_emitcode ("orl","a,b");
+        DEBUGpic16_emitcode(";", "rLen = %i", rLen);
+        pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
+        pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
+//        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
+//        pic16_emitcode ("orl","a,b");
     }
 
-    if (p_type == GPOINTER)
-        pic16_emitcode("pop","b");
+//    if (p_type == GPOINTER)
+//        pic16_emitcode("pop","b");
 
     switch (p_type) {
 
-    case POINTER:
-       pic16_emitcode("mov","@%s,a",rname);
+      case POINTER:
+        pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+//     pic16_emitcode("mov","@%s,a",rname);
        break;
-       
-    case FPOINTER:
+/*
+      case FPOINTER:
        pic16_emitcode("movx","@dptr,a");
        break;
        
-    case GPOINTER:
+      case GPOINTER:
        DEBUGpic16_emitcode(";lcall","__gptrput");
        break;                  
+*/
+      default:
+        assert(0);
     }
+    
+//    pic16_freeAsmop(right, NULL, ic, TRUE);
 }
 /*-----------------------------------------------------------------*/
 /* genDataPointerSet - remat pointer to data space                 */
@@ -11914,7 +12087,6 @@ static void genNearPointerSet (operand *right,
                                iCode *ic)
 {
   asmop *aop = NULL;
-  char *l;
   sym_link *retype;
   sym_link *ptype = operandType(result);
   sym_link *resetype;
@@ -11946,33 +12118,15 @@ 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))) {
-               /* otherwise get a free pointer register */
-               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
-//             if( (AOP_TYPE(result) == AOP_PCODE) 
-//                     && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
-//                             || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
-                if(is_LitAOp( AOP(result) ))
-               {
-                 if(!IS_BITFIELD(resetype))
-                       pic16_loadFSR0( result );  // patch 10
-               } else {
-                 if(!IS_BITFIELD(resetype)) {
-                       // set up FSR0 with address of result
-                       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
-                       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
-                  }
-               }
+       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__);
 
-       }
-//     else
-//     rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
+         ;
+        }
 
        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-//     pic16_loadFSR0( result );
-
        /* if bitfield then unpack the bits */
        if (IS_BITFIELD(resetype)) {
                genPackBits (resetype, result, right, NULL, POINTER);
@@ -11981,15 +12135,10 @@ static void genNearPointerSet (operand *right,
          int size = AOP_SIZE(right);
          int offset = 0 ;    
 
+           pic16_loadFSR0(result, 0);
+           
                DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
                while (size--) {
-                       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
-                       if (*l == '@' ) {
-                               //MOVA(l);
-                               //pic16_emitcode("mov","@%s,a",rname);
-                               pic16_emitcode("movf","indf0,w ;1");
-                       } else {
-
                                if (AOP_TYPE(right) == AOP_LIT) {
                                        pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
                                        if (size) {
@@ -12008,41 +12157,40 @@ static void genNearPointerSet (operand *right,
                                                                        pic16_popCopyReg(&pic16_pc_indf0)));
                                        }
                                }
-                       }
                        offset++;
                }
-       }
+        }
 
        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        /* now some housekeeping stuff */
        if (aop) {
-               /* we had to allocate for this iCode */
-               pic16_freeAsmop(NULL,aop,ic,TRUE);
+         /* we had to allocate for this iCode */
+          pic16_freeAsmop(NULL,aop,ic,TRUE);
        } else { 
-               /* we did not allocate which means left
-                * already in a pointer register, then
-                * if size > 0 && this could be used again
-                * we have to point it back to where it 
-                * belongs */
-               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-               if (AOP_SIZE(right) > 1
-                       && !OP_SYMBOL(result)->remat
-                       && ( OP_SYMBOL(result)->liveTo > ic->seq
-                               || ic->depth )) {
-
-                 int size = AOP_SIZE(right) - 1;
-
-                       while (size--)
-                               pic16_emitcode("decf","fsr0,f");
-                       //pic16_emitcode("dec","%s",rname);
-               }
-       }
+         /* we did not allocate which means left
+          * already in a pointer register, then
+          * if size > 0 && this could be used again
+          * we have to point it back to where it 
+          * belongs */
+         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+         if (AOP_SIZE(right) > 1
+           && !OP_SYMBOL(result)->remat
+           && ( OP_SYMBOL(result)->liveTo > ic->seq
+           || ic->depth )) {
+
+             int size = AOP_SIZE(right) - 1;
+
+               while (size--)
+                 pic16_emitcode("decf","fsr0,f");
+                 //pic16_emitcode("dec","%s",rname);
+            }
+        }
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       /* done */
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* done */
 //release:
-       pic16_freeAsmop(right,NULL,ic,TRUE);
-       pic16_freeAsmop(result,NULL,ic,TRUE);
+    pic16_freeAsmop(right,NULL,ic,TRUE);
+    pic16_freeAsmop(result,NULL,ic,TRUE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -12369,6 +12517,7 @@ static void genGenPointerSet (operand *right,
       symbol *sym;
                   
         sym = newSymbol( fgptrput, 0 );
+        sym->used++;
         strcpy(sym->rname, fgptrput);
         checkAddSym(&externs, sym);
     }
@@ -12730,7 +12879,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),
@@ -12738,8 +12887,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++;
@@ -13274,7 +13424,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:
@@ -13470,10 +13626,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
 }
 
 /*-----------------------------------------------------------------*/