* src/pic16/gen.c (pic16_derefPtr): NEW, single place
[fw/sdcc] / src / pic16 / gen.c
index 26ad8236cdd117d8992744dd0aa4d0f2c57fb2c1..b3fd810568a562041fd30adaa7cf35fb97a3d7e4 100644 (file)
@@ -7,6 +7,7 @@
   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
              -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
+  Bug Fixes  -  Raphael Neider rneider@web.de (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
@@ -68,7 +69,6 @@ extern void pic16_printpBlock(FILE *of, pBlock *pb);
 static asmop *newAsmop (short type);
 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
-static void mov2f(asmop *dst, asmop *src, int offset);
 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
 static pCodeOp *pic16_popRegFromIdx(int rIdx);
 
@@ -303,7 +303,9 @@ void pic16_emitpLabelFORCE(int key)
   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
 }
 
-void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
+/* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
+ * NEVER call pic16_emitpcode_real directly, please... */
+void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
 {
 
   if(pcop)
@@ -1270,7 +1272,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
                                                  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__);
+         pic16_emitpcomment (";!!! %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);
        }
@@ -1791,17 +1793,20 @@ pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
   pCodeOpReg *pcor;
 
   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
-  pcor->pcop.type = pc->pcop.type;
+  memcpy (pcor, pc, sizeof (pCodeOpReg));
+  pcor->r->wasUsed = 1;
+  
+  //pcor->pcop.type = pc->pcop.type;
   if(pc->pcop.name) {
     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
   } else
     pcor->pcop.name = NULL;
 
-  pcor->r = pc->r;
-  pcor->rIdx = pc->rIdx;
-  pcor->r->wasUsed=1;
-  pcor->instance = pc->instance;
+  //pcor->r = pc->r;
+  //pcor->rIdx = pc->rIdx;
+  //pcor->r->wasUsed=1;
+  //pcor->instance = pc->instance;
 
 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
 
@@ -2380,7 +2385,7 @@ void pic16_mov2w (asmop *aop, int offset)
     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
 }
 
-static void mov2f(asmop *dst, asmop *src, int offset)
+void pic16_mov2f(asmop *dst, asmop *src, int offset)
 {
   if(is_LitAOp(src)) {
     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
@@ -2788,7 +2793,7 @@ static void genUminusFloat(operand *op,operand *result)
     size = AOP_SIZE(op);
 
     while(size--) {
-      mov2f(AOP(result), AOP(op), offset);
+      pic16_mov2f(AOP(result), AOP(op), offset);
       offset++;
     }
     
@@ -3663,14 +3668,16 @@ static void genFunction (iCode *ic)
          * wrapper segment at vector address. The user should take care for
          * this instead. -- VR */
 
-        if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) =! INTNO_UNSPEC)) {
+        if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
           asym = newSymbol(asymname, 0);
           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
           pic16_addpBlock( apb );
 
           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
-          pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
+          //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
+          //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
+         pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
                
           /* mark the end of this tiny function */
           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
@@ -5050,7 +5057,7 @@ static void genCmp (operand *left,operand *right,
     left = right;
     right = dummy;
 
-    performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
+    performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
   } else if (isAOP_LIT(right)) {
     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
   } // if
@@ -5813,7 +5820,7 @@ static void genCmp (operand *left,operand *right,
        
        pctemp = pic16_popGetTempReg(1);
        pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
-       pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
+       pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
        pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
        pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
@@ -6151,7 +6158,6 @@ static void genCmp (operand *left, operand *right,
 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
           }
-//        }
         
         if(ifx)ifx->generated = 1;
 
@@ -8223,7 +8229,6 @@ static void genXor (iCode *ic, iCode *ifx)
 static void genInline (iCode *ic)
 {
   char *buffer, *bp, *bp1;
-  char *cbuf;
     
        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
@@ -8239,12 +8244,14 @@ static void genInline (iCode *ic)
         }
         bp = bp1 = buffer;
 
-       cbuf = Safe_strdup( buffer );
-
+#if 0
+  /* This is an experimental code for #pragma inline
+     and is temporarily disabled for 2.5.0 release */
         if(asmInlineMap)
         {
           symbol *sym;
           char *s;
+          char *cbuf;
           int cblen;
 
             cbuf = Safe_strdup(buffer);
@@ -8291,6 +8298,7 @@ static void genInline (iCode *ic)
             
             bp = bp1 = buffer;
         }
+#endif  /* 0 */
 
        /* emit each line as a code */
        while (*bp) {
@@ -8689,7 +8697,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl,
     } else {
       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
     }
@@ -8704,7 +8712,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl,
     } else {
       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
     }
 
   default:
@@ -9544,7 +9552,7 @@ static void genLeftShift (iCode *ic)
 #endif
       {
         /* we don't know if left is a literal or a register, take care -- VR */
-        mov2f(AOP(result), AOP(left), offset);
+        pic16_mov2f(AOP(result), AOP(left), offset);
       }
       offset++;
     }
@@ -9576,7 +9584,7 @@ static void genLeftShift (iCode *ic)
 #if 1
       /* this is already done, why change it? */
       if (!pic16_sameRegs(AOP(left),AOP(result))) {
-                mov2f(AOP(result), AOP(left), 0);
+                pic16_mov2f(AOP(result), AOP(left), 0);
       }
 #endif
 
@@ -9727,7 +9735,7 @@ static void genLeftShift (iCode *ic)
       } else {
 
         /* we don't know if left is a literal or a register, take care -- VR */
-        mov2f(AOP(result), AOP(left), offset);
+        pic16_mov2f(AOP(result), AOP(left), offset);
       }
       offset++;
     }
@@ -9756,7 +9764,7 @@ static void genLeftShift (iCode *ic)
 
       tlbl = newiTempLabel(NULL);
       if (!pic16_sameRegs(AOP(left),AOP(result))) {
-                mov2f(AOP(result), AOP(left), 0);
+                pic16_mov2f(AOP(result), AOP(left), 0);
                 
 //             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
 //             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
@@ -9882,7 +9890,7 @@ static void genrshTwo (operand *result,operand *left,
 
     if(sign) {
       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-      pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
+      pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),MSB16));
     }
   }
 
@@ -10043,7 +10051,7 @@ static void genRightShiftLiteral (operand *left,
   if(shCount == 0){
     assert (res_size <= lsize);
     while (res_size--) {
-      mov2f (AOP(result), AOP(left), res_size);
+      pic16_mov2f (AOP(result), AOP(left), res_size);
     } // for
   }
 
@@ -10053,7 +10061,7 @@ static void genRightShiftLiteral (operand *left,
       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
       if(sign) {
        pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
+       pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
       }
     } else {
 
@@ -10422,7 +10430,7 @@ static void genGenericShift (iCode *ic, int isShiftLeft) {
   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
-    mov2f (AOP(result),AOP(left), offset);
+    pic16_mov2f (AOP(result),AOP(left), offset);
   } // for
 
   // if result is longer than left, fill with zeros (or sign)
@@ -10527,17 +10535,64 @@ void pic16_loadFSR0(operand *op, int lit)
   }
 }
 
+/*----------------------------------------------------------------*/
+/* pic16_derefPtr - move one byte from the location ptr points to */
+/*                  to WREG (doWrite == 0) or one byte from WREG   */
+/*                  to the location ptr points to (doWrite != 0)   */
+/*----------------------------------------------------------------*/
+static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
+{
+  switch (p_type) {
+    case FPOINTER:
+    case POINTER:
+      if (!fsr0_setup || !*fsr0_setup)
+      {
+        pic16_loadFSR0( ptr, 0 );
+        if (fsr0_setup) *fsr0_setup = 1;
+      }
+      if (doWrite)
+        pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+      else
+        pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
+      break;
+
+    case GPOINTER:
+      if (AOP(ptr)->aopu.aop_reg[2]) {
+        if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
+       // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
+       pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
+       pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
+       pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
+       pic16_callGenericPointerRW(doWrite, 1);
+      } else {
+       // data pointer (just 2 byte given)
+       if (!fsr0_setup || !*fsr0_setup)
+       {
+         pic16_loadFSR0( ptr, 0 );
+         if (fsr0_setup) *fsr0_setup = 1;
+       }
+       if (doWrite)
+         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+       else
+         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
+      }
+      break;
+
+    default:
+      assert (0 && "invalid pointer type specified");
+      break;
+  }
+}
+
 /*-----------------------------------------------------------------*/
 /* genUnpackBits - generates code for unpacking bits               */
 /*-----------------------------------------------------------------*/
 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
 {    
   int shCnt ;
-  int rlen = 0 ;
   sym_link *etype, *letype;
   int blen=0, bstr=0;
   int lbstr;
-  int offset = 0 ;
 
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
     etype = getSpec(operandType(result));
@@ -10558,7 +10613,7 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp
       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
       
       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
-      if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
+      if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
         /* workaround to reduce the extra lfsr instruction */
         pic16_emitpcode(POC_BTFSC,
               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
@@ -10580,27 +10635,11 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp
          * optimization to handle single bit assignments is added
          * to the function. Until then use the old safe way! -- VR */
 
-    if (OP_SYMBOL(left)->remat) {
+    if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
        // access symbol directly
        pic16_mov2w (AOP(left), 0);
     } else {
-        pic16_loadFSR0( left, 0 );
-       /* read the first byte  */
-       switch (ptype) {
-               case POINTER:
-               case IPOINTER:
-               case PPOINTER:
-               case FPOINTER:
-               case GPOINTER:
-                       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
-                       break;
-               case CPOINTER:
-                       pic16_emitcode("clr","a");
-                       pic16_emitcode("movc","a","@a+dptr");
-                       assert (0);
-                       break;
-       }
+      pic16_derefPtr (left, ptype, 0, NULL);
     }
 
        /* if we have bitdisplacement then it fits   */
@@ -10632,55 +10671,6 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp
        fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
        exit(-1);
 
-    /* bit field did not fit in a byte  */
-    rlen = SPEC_BLEN(etype) - 8;
-    pic16_aopPut(AOP(result),"a",offset++);
-
-    while (1)  {
-
-       switch (ptype) {
-       case POINTER:
-       case IPOINTER:
-           pic16_emitcode("inc","%s",rname);
-           pic16_emitcode("mov","a,@%s",rname);
-           break;
-           
-       case PPOINTER:
-           pic16_emitcode("inc","%s",rname);
-           pic16_emitcode("movx","a,@%s",rname);
-           break;
-
-       case FPOINTER:
-           pic16_emitcode("inc","dptr");
-           pic16_emitcode("movx","a,@dptr");
-           break;
-           
-       case CPOINTER:
-           pic16_emitcode("clr","a");
-           pic16_emitcode("inc","dptr");
-           pic16_emitcode("movc","a","@a+dptr");
-           break;
-           
-       case GPOINTER:
-           pic16_emitcode("inc","dptr");
-           pic16_emitcode("lcall","__gptrget");
-           break;
-       }
-
-       rlen -= 8;            
-       /* if we are done */
-       if ( rlen <= 0 )
-           break ;
-       
-       pic16_aopPut(AOP(result),"a",offset++);
-                                     
-    }
-    
-    if (rlen) {
-       pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
-       pic16_aopPut(AOP(result),"a",offset);          
-    }
-    
     return ;
 }
 
@@ -10776,12 +10766,14 @@ static void genNearPointerGet (operand *left,
 //  asmop *aop = NULL;
   //regs *preg = NULL ;
   sym_link *rtype, *retype;
-  sym_link *ltype = operandType(left);    
+  sym_link *ltype, *letype;
 
     FENTRY;
     
     rtype = operandType(result);
     retype= getSpec(rtype);
+    ltype = operandType(left);
+    letype= getSpec(ltype);
     
     pic16_aopOp(left,ic,FALSE);
 
@@ -10848,18 +10840,8 @@ static void genNearPointerGet (operand *left,
     }
 #endif
 
-
-    /* if the value is already in a pointer register
-     * then don't need anything more */
-    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__);
-               
-      ;
-    }
-
     /* if bitfield then unpack the bits */
-    if (IS_BITFIELD(retype)) 
+    if (IS_BITFIELD(letype)) 
       genUnpackBits (result, left, NULL, POINTER);
     else {
       /* we have can just get the values */
@@ -11168,7 +11150,7 @@ static void genGenPointerGet (operand *left,
                               operand *result, iCode *ic)
 {
   int size, offset, lit;
-  sym_link *retype = getSpec(operandType(result));
+  sym_link *letype = getSpec(operandType(left));
 
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
     pic16_aopOp(left,ic,FALSE);
@@ -11176,6 +11158,12 @@ static void genGenPointerGet (operand *left,
     size = AOP_SIZE(result);
 
     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
+  
+    /* if bit then unpack */
+    if (IS_BITFIELD(letype)) {
+      genUnpackBits(result,left,"BAD",GPOINTER);
+      goto release;
+    }
 
     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
 
@@ -11211,10 +11199,6 @@ static void genGenPointerGet (operand *left,
       goto release;
     }
 
-  /* if bit then unpack */
-    if (IS_BITFIELD(retype)) 
-      genUnpackBits(result,left,"BAD",GPOINTER);
-
 release:
   pic16_freeAsmop(left,NULL,ic,TRUE);
   pic16_freeAsmop(result,NULL,ic,TRUE);
@@ -11468,46 +11452,13 @@ static void genPackBits (sym_link    *etype , operand *result,
                  /* using PRODH as a temporary register here */
                  pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
 
-                if (OP_SYMBOL(result)->remat) {
-                  // access symbol directly
-                  pic16_mov2w (AOP(result), 0);
-                } else {
-                 /* get old value */
-                 switch (p_type) {
-                       case FPOINTER:
-                       case POINTER:
-                               pic16_loadFSR0( result, 0 );
-                               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:
-                               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_callGenericPointerRW(0, 1);
-                               } else {
-                                 // data pointer (just 2 byte given)
-                                 pic16_loadFSR0( result, 0 );
-                                 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 (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
+                   /* access symbol directly */
+                   pic16_mov2w (AOP(result), 0);
+                 } else {
+                   /* get old value */
+                   pic16_derefPtr (result, p_type, 0, &fsr0_setup);
                  }
-                }
 #if 1
                  pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
                        (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
@@ -11516,40 +11467,10 @@ static void genPackBits (sym_link    *etype , operand *result,
                } // if (blen != 8 || bstr != 0)
 
                /* write new value back */
-              if (OP_SYMBOL(result)->remat) {
-               pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
-              } else {
-               switch (p_type) {
-                       case FPOINTER:
-                       case POINTER:
-                               if (!fsr0_setup) pic16_loadFSR0( result, 0 );
-                               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_callGenericPointerRW(1, 1);
-                               } else {
-                                 // data pointer (just 2 byte given)
-                                 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
-                                 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;
-               }
+               if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
+                 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
+               } else {
+                 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
               }
 #endif
 
@@ -11758,17 +11679,6 @@ static void genNearPointerSet (operand *right,
        pic16_aopOp(right,ic,FALSE);
        DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
 
-       /* if the value is already in a pointer register
-        * then don't need anything more */
-       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__);
-
-         ;
-        }
-
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
        /* if bitfield then unpack the bits */
        if (IS_BITFIELD(resetype)) {
                genPackBits (resetype, result, right, NULL, POINTER);
@@ -12097,7 +12007,7 @@ static void genGenPointerSet (operand *right,
                               operand *result, iCode *ic)
 {
   int size;
-  sym_link *retype = getSpec(operandType(right));
+  sym_link *retype = getSpec(operandType(result));
 
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
@@ -12120,7 +12030,6 @@ static void genGenPointerSet (operand *right,
     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
 
 
-
     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
 
     /* value of right+0 is placed on stack, which will be retrieved
@@ -12165,6 +12074,7 @@ static void genPointerSet (iCode *ic)
     move it to the correct pointer register */
     type = operandType(result);
     etype = getSpec(type);
+    
     /* if left is of type of pointer then it is simple */
     if (IS_PTR(type) && !IS_FUNC(type->next)) {
         p_type = DCL_TYPE(type);
@@ -12467,16 +12377,21 @@ static void genAssign (iCode *ic)
   if (AOP_TYPE(right) == AOP_REG) {
     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
     while (size--) {
-      
       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
     } // while
     goto release;
   }
 
+  /* when do we have to read the program memory?
+   * - if right itself is a symbol in code space
+   *   (we don't care what it points to if it's a pointer)
+   * - AND right is not a function (we would want its address)
+   */
   if(AOP_TYPE(right) != AOP_LIT
-       && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
+       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
        && !IS_FUNC(OP_SYM_TYPE(right))
-       ) {
+       && !IS_ITEMP(right))
+  {
        DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
        fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
 
@@ -12499,7 +12414,8 @@ static void genAssign (iCode *ic)
                                pic16_popCopyReg(&pic16_pc_tblptru)));
        }
 
-       size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
+       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
+       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
        while(size--) {
                pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
@@ -12507,7 +12423,9 @@ static void genAssign (iCode *ic)
                offset++;
        }
 
-       size = getSize(OP_SYM_ETYPE(right));
+       /* FIXME: for pointers we need to extend differently (according
+        * to pointer type DATA/CODE/EEPROM/... :*/
+       size = getSize(OP_SYM_TYPE(right));
        if(AOP_SIZE(result) > size) {
                size = AOP_SIZE(result) - size;
                while(size--) {
@@ -13005,7 +12923,7 @@ static void genCast (iCode *ic)
            while (size--) {
              if(offset < AOP_SIZE(right)) {
                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
-                mov2f(AOP(result), AOP(right), offset);
+                pic16_mov2f(AOP(result), AOP(right), offset);
 /*
                if ((AOP_TYPE(right) == AOP_PCODE) && 
                    AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
@@ -13096,7 +13014,7 @@ static void genCast (iCode *ic)
 
     while (size--) {
       if(!_G.resDirect)
-        mov2f(AOP(result), AOP(right), offset);
+        pic16_mov2f(AOP(result), AOP(right), offset);
       offset++;
     }
 
@@ -13113,7 +13031,7 @@ static void genCast (iCode *ic)
        /* Save one instruction of casting char to int */
        pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
        pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-       pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
+       pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
       } else {
         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));