* src/pic/gen.c: handle FPOINTERS like POINTERS everywhere
authortecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Fri, 11 Nov 2005 23:09:56 +0000 (23:09 +0000)
committertecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Fri, 11 Nov 2005 23:09:56 +0000 (23:09 +0000)
* src/pic16/gen.c (pic16_derefPtr): now works for non-pointers as well,
  compute pointer's type from operand,
  (genUnpackBits,genPackBits): handle FPOINTERS correctly, re-indented,
  improved single bit reads, fixes bug #1353379

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3946 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/pic/gen.c
src/pic16/gen.c

index 5fecc7c9c4190ef26914d06f77a50b6daa072ed5..a53cba076448a9e2839b73d5d9a3e892b1c14251 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2005-11-11 Raphael Neider <rneider AT web.de>
+
+       * src/pic/gen.c: handle FPOINTERS like POINTERS everywhere
+       * src/pic16/gen.c (pic16_derefPtr): now works for non-pointers as well,
+         compute pointer's type from operand,
+         (genUnpackBits,genPackBits): handle FPOINTERS correctly, re-indented,
+         improved single bit reads, fixes bug #1353379
+
 2005-11-09 Borut Razem <borut.razem AT siol.net>
 
        * support/scripts/sdcc.nsi: added lib/pic to the package
index 9a221d2572e7dc313a9e59175548df408d33b20b..4a4a18906c8bd0f0127f55cbb56259bbacc8d1b5 100644 (file)
 #define GPTRTAG_DATA   0x00
 #define GPTRTAG_CODE   0x80
 
+/* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
+#define PIC_IS_DATA_PTR(x)     (IS_DATA_PTR(x) || IS_FARPTR(x))
+#define PIC_IS_FARPTR(x)       (PIC_IS_DATA_PTR(x))
+
 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 void genMult8X8_8 (operand *, operand *,operand *);
@@ -8450,6 +8454,7 @@ emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
     switch (p_type)
     {
     case POINTER:
+    case FPOINTER:
       if (!alreadyAddressed) setup_fsr (src);
       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
       break;
@@ -8491,6 +8496,7 @@ emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
     switch (p_type)
     {
     case POINTER:
+    case FPOINTER:
       if (!alreadyAddressed) setup_fsr (dst);
       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
       break;
@@ -8559,6 +8565,7 @@ static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx
         break;
        
       case POINTER:
+      case FPOINTER:
       case GPOINTER:
       case CPOINTER:
         emitPtrByteGet (left, ptype, FALSE);
@@ -8596,6 +8603,7 @@ static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx
       break;
       
     case POINTER:
+    case FPOINTER:
     case GPOINTER:
     case CPOINTER:
       emitPtrByteGet (left, ptype, FALSE);
@@ -8692,7 +8700,7 @@ static void genNearPointerGet (operand *left,
        lower 128 bytes of space */
        if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
                !IS_BITVAR(retype)         &&
-               DCL_TYPE(ltype) == POINTER) {
+               PIC_IS_DATA_PTR(ltype)) {
                genDataPointerGet (left,result,ic);
                return ;
        }
@@ -9126,6 +9134,7 @@ static void genPointerGet (iCode *ic)
        switch (p_type) {
                
        case POINTER: 
+       case FPOINTER:
        //case IPOINTER:
                genNearPointerGet (left,result,ic);
                break;
@@ -9192,6 +9201,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
          setup_fsr (result);
          emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
          break;
@@ -9231,6 +9241,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
        case GPOINTER:
          emitPtrByteGet(result, p_type, FALSE);
          if ((litval|mask) != 0x00ff)
@@ -9267,6 +9278,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
        case GPOINTER:
          emitPtrByteGet (result, p_type, FALSE);
          emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
@@ -9308,6 +9320,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
        case GPOINTER:
          emitPtrByteGet (result, p_type, FALSE);
          emitpcode(POC_ANDLW, popGetLit (mask));
@@ -9449,7 +9462,7 @@ static void genNearPointerSet (operand *right,
        in data space & not a bit variable */
        //if (AOP_TYPE(result) == AOP_IMMD &&
        if (AOP_TYPE(result) == AOP_PCODE &&
-               DCL_TYPE(ptype) == POINTER   &&
+               PIC_IS_DATA_PTR(ptype) &&
                !IS_BITVAR (retype) &&
                !IS_BITVAR (letype)) {
                genDataPointerSet (right,result,ic);
@@ -9774,6 +9787,7 @@ static void genPointerSet (iCode *ic)
        switch (p_type) {
                
        case POINTER:
+       case FPOINTER:
        //case IPOINTER:
                genNearPointerSet (right,result,ic);
                break;
index 1f03cbb6dc5ce87cdcf75aea1756338afc060bec..ca0e63d253be48ae66d85a7823e3a815f07c985f 100644 (file)
  * more reliable and (sigh) slighly slower. */
 #define USE_SIMPLE_GENCMP 1
 
+/* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
+#define PIC_IS_DATA_PTR(x)     (IS_DATA_PTR(x) || IS_FARPTR(x))
+#define PIC_IS_FARPTR(x)       (IS_DATA_PTR(x) || IS_FARPTR(x))
+
 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 void pic16_genMult8X8_8 (operand *, operand *,operand *);
@@ -10449,6 +10453,17 @@ void pic16_loadFSR0(operand *op, int lit)
 /*----------------------------------------------------------------*/
 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
 {
+  if (!IS_PTR(operandType(ptr)))
+  {
+    if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
+    else pic16_mov2w (AOP(ptr), 0);
+    return;
+  }
+
+  //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
+  /* We might determine pointer type right here: */
+  p_type = DCL_TYPE(operandType(ptr));
+
   switch (p_type) {
     case FPOINTER:
     case POINTER:
@@ -10500,107 +10515,105 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp
   sym_link *etype, *letype;
   int blen=0, bstr=0;
   int lbstr;
+  int same;
+  pCodeOp *op;
 
-    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-    etype = getSpec(operandType(result));
-    letype = getSpec(operandType(left));
-    
-//    if(IS_BITFIELD(etype)) {
-      blen = SPEC_BLEN(etype);
-      bstr = SPEC_BSTR(etype);
-//    }
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  etype = getSpec(operandType(result));
+  letype = getSpec(operandType(left));
 
-    lbstr = SPEC_BSTR( letype );
+  //    if(IS_BITFIELD(etype)) {
+  blen = SPEC_BLEN(etype);
+  bstr = SPEC_BSTR(etype);
+  //    }
 
-    DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
-       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
-    
-#if 1
-    if((blen == 1) && (bstr < 8)) {
-      /* it is a single bit, so use the appropriate bit instructions */
-      DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
+  lbstr = SPEC_BSTR( letype );
 
-      pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-      
-      // distinguish (p->bitfield) and p.bitfield, remat seems to work...
-      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));
-      } else {
-        /* this code does only handle __data pointers correctly */
-        assert (IS_DATA_PTR(operandType(left)));
-       pic16_loadFSR0 (left, 0);
-        pic16_emitpcode(POC_BTFSC,
-              pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
-      }
+  DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
+      SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
 
-      if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
-        /* unsigned bitfields result in either 0 or 1 */
-        pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
-      } else {
-        /* signed bitfields result in either 0 or -1 */
-        pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_wreg));
-      }
-      pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
-      
-      pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
-      return;
+#if 1
+  if((blen == 1) && (bstr < 8)
+      && (!IS_PTR(operandType(left)) || PIC_IS_DATA_PTR(operandType(left)))) {
+    /* it is a single bit, so use the appropriate bit instructions */
+    DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
+
+    same = pic16_sameRegs(AOP(left),AOP(result));
+    op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
+    pic16_emitpcode(POC_CLRF, op);
+
+    if(!IS_PTR(operandType(left))) {
+      /* workaround to reduce the extra lfsr instruction */
+      pic16_emitpcode(POC_BTFSC,
+         pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
+    } else {
+      assert (PIC_IS_DATA_PTR (operandType(left)));
+      pic16_loadFSR0 (left, 0);
+      pic16_emitpcode(POC_BTFSC,
+         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
     }
 
-#endif
-
-        /* 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 */
-
-    if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
-       // access symbol directly
-       pic16_mov2w (AOP(left), 0);
+    if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
+      /* unsigned bitfields result in either 0 or 1 */
+      pic16_emitpcode(POC_INCF, op);
     } else {
-      pic16_derefPtr (left, ptype, 0, NULL);
+      /* signed bitfields result in either 0 or -1 */
+      pic16_emitpcode(POC_DECF, op);
+    }
+    if (same) {
+      pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
     }
 
-       /* if we have bitdisplacement then it fits   */
-       /* into this byte completely or if length is */
-       /* less than a byte                          */
-       if ((shCnt = SPEC_BSTR(etype)) || 
-               (SPEC_BLEN(etype) <= 8))  {
-
-               /* shift right acc */
-               AccRsh(shCnt, 0);
+    pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
+    return;
+  }
 
-               pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
-                       (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
+#endif
 
-/* VR -- normally I would use the following, but since we use the hack,
- * to avoid the masking from AccRsh, why not mask it right now? */
+  if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
+    // access symbol directly
+    pic16_mov2w (AOP(left), 0);
+  } else {
+    pic16_derefPtr (left, ptype, 0, NULL);
+  }
 
-/*
-               pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
-*/
+  /* if we have bitdisplacement then it fits   */
+  /* into this byte completely or if length is */
+  /* less than a byte                          */
+  if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
 
-               /* extend signed bitfields to 8 bits */
-               if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
-               {
-                       assert (blen + bstr > 0);
-                       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
-                       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
-               }
+    /* shift right acc */
+    AccRsh(shCnt, 0);
 
-               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+    pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
+         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
 
-               pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
-         return ;
-       }
+    /* VR -- normally I would use the following, but since we use the hack,
+     * to avoid the masking from AccRsh, why not mask it right now? */
 
+    /*
+       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
+     */
 
+    /* extend signed bitfields to 8 bits */
+    if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
+    {
+      assert (blen + bstr > 0);
+      pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
+      pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
+    }
 
-       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);
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
 
+    pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
     return ;
+  }
+
+  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);
+
+  return ;
 }
 
 
@@ -11299,222 +11312,227 @@ static void genPackBits (sym_link    *etype , operand *result,
   int blen, bstr ;   
   sym_link *retype;
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       blen = SPEC_BLEN(etype);
-       bstr = SPEC_BSTR(etype);
+  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  blen = SPEC_BLEN(etype);
+  bstr = SPEC_BSTR(etype);
 
-       retype = getSpec(operandType(right));
+  retype = getSpec(operandType(right));
 
-       if(AOP_TYPE(right) == AOP_LIT) {
-               if((blen == 1) && (bstr < 8)) {
-                 unsigned long lit;
-                       /* it is a single bit, so use the appropriate bit instructions */
+  if(AOP_TYPE(right) == AOP_LIT) {
+    if((blen == 1) && (bstr < 8)) {
+      unsigned long lit;
+      /* it is a single bit, so use the appropriate bit instructions */
 
-                       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
+      DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
 
-                       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-//                     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
-                       if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
-                               /* workaround to reduce the extra lfsr instruction */
-                               if(lit) {
-                                       pic16_emitpcode(POC_BSF,
-                                               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
-                               } else {
-                                       pic16_emitpcode(POC_BCF,
-                                               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
-                               }
-                       } else {
-                                pic16_loadFSR0(result, 0);
-                               if(lit) {
-                                       pic16_emitpcode(POC_BSF,
-                                               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
-                               } else {
-                                       pic16_emitpcode(POC_BCF,
-                                               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
-                               }
-                       }
-       
-                 return;
-               }
-                /* move literal to W */
-               pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
-               offset++;
-       } else
-       if(IS_BITFIELD(retype) 
-         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
-         && (blen == 1)) {
-         int rblen, rbstr;
+      lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+      //                       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
+      if(!IS_PTR(operandType(result))) {
+       /* workaround to reduce the extra lfsr instruction */
+       if(lit) {
+         pic16_emitpcode(POC_BSF,
+             pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
+       } else {
+         pic16_emitpcode(POC_BCF,
+             pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
+       }
+      } else {
+       if (PIC_IS_DATA_PTR(operandType(result))) {
+         pic16_loadFSR0(result, 0);
+         pic16_emitpcode(lit ? POC_BSF : POC_BCF,
+             pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
+       } else {
+         /* get old value */
+         pic16_derefPtr (result, p_type, 0, NULL);
+         pic16_emitpcode(lit ? POC_BSF : POC_BCF,
+             pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
+         /* write back new value */
+         pic16_derefPtr (result, p_type, 1, NULL);
+       }
+      }
 
-           rblen = SPEC_BLEN( retype );
-           rbstr = SPEC_BSTR( retype );
-           
+      return;
+    }
+    /* move literal to W */
+    pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
+    offset++;
+  } else
+    if(IS_BITFIELD(retype) 
+       && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
+       && (blen == 1)) {
+      int rblen, rbstr;
 
-            if(IS_BITFIELD(etype)) {
-              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
-              pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
-            } else {
-              pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-            }
-            
-           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
-           
-           if(IS_BITFIELD(etype)) {
-             pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
-            } else {
-              pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
-            }
+      rblen = SPEC_BLEN( retype );
+      rbstr = SPEC_BSTR( retype );
 
-            pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
-            
-            return;
-        } else {
-          /* move right to W */
-          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
-        }
 
-       /* 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;
-
-               if (blen != 8 || bstr != 0) {
-                 // we need to combine the value with the old value
-                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
-
-         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
-               SPEC_BSTR(etype), SPEC_BLEN(etype));
-               
-                 /* shift left acc */
-                 AccLsh(shCnt);
-
-                 /* using PRODH as a temporary register here */
-                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
-
-                 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)) |
-                                       (unsigned char)(0xff >> (8-bstr))) ));
-                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
-               } // if (blen != 8 || bstr != 0)
-
-               /* write new value back */
-               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
+      if(IS_BITFIELD(etype)) {
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
+       pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
+      } else {
+       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+      }
 
-         return;
-       }
+      pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
 
+      if(IS_BITFIELD(etype)) {
+       pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
+      } else {
+       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
+      }
 
-#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
+      pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
 
+      return;
+    } else {
+      /* move right to W */
+      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
+    }
 
-    pic16_loadFSR0(result, 0);                 // load FSR0 with address of result
-    rLen = SPEC_BLEN(etype)-8;
-    
-    /* now generate for lengths greater than one byte */
-    while (1) {
-        rLen -= 8 ;
-        if (rLen <= 0 ) {
-          mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
-          break ;
-        }
+  /* 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;
 
-        switch (p_type) {
-            case POINTER:
-                  pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
-                break;
+    if (blen != 8 || bstr != 0) {
+      // we need to combine the value with the old value
+      pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
 
-/*
-            case FPOINTER:
-                MOVA(l);
-                pic16_emitcode("movx","@dptr,a");
-                break;
+      DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
+         SPEC_BSTR(etype), SPEC_BLEN(etype));
 
-            case GPOINTER:
-                MOVA(l);
-                DEBUGpic16_emitcode(";lcall","__gptrput");
-                break;  
-*/
-          default:
-            assert(0);
-        }   
+      /* shift left acc */
+      AccLsh(shCnt);
 
+      /* using PRODH as a temporary register here */
+      pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
 
-        pic16_mov2w(AOP(right), offset++);
+      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)) |
+                           (unsigned char)(0xff >> (8-bstr))) ));
+      pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
+    } // if (blen != 8 || bstr != 0)
+
+    /* write new value back */
+    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
 
-    /* last last was not complete */
-    if (rLen)   {
-        /* save the byte & read byte */
-        switch (p_type) {
-            case POINTER:
-//                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
-                pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
-                break;
+    return;
+  }
 
-/*
-            case FPOINTER:
-                pic16_emitcode ("mov","b,a");
-                pic16_emitcode("movx","a,@dptr");
-                break;
 
-            case GPOINTER:
-                pic16_emitcode ("push","b");
-                pic16_emitcode ("push","acc");
-                pic16_emitcode ("lcall","__gptrget");
-                pic16_emitcode ("pop","b");
-                break;
-*/
-            default:
-              assert(0);
-        }
-        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 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 (p_type == GPOINTER)
-//        pic16_emitcode("pop","b");
 
-    switch (p_type) {
+  pic16_loadFSR0(result, 0);                   // load FSR0 with address of result
+  rLen = SPEC_BLEN(etype)-8;
+
+  /* now generate for lengths greater than one byte */
+  while (1) {
+    rLen -= 8 ;
+    if (rLen <= 0 ) {
+      mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
+      break ;
+    }
 
+    switch (p_type) {
       case POINTER:
-        pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
-//     pic16_emitcode("mov","@%s,a",rname);
+       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
        break;
-/*
-      case FPOINTER:
-       pic16_emitcode("movx","@dptr,a");
+
+       /*
+          case FPOINTER:
+          MOVA(l);
+          pic16_emitcode("movx","@dptr,a");
+          break;
+
+          case GPOINTER:
+          MOVA(l);
+          DEBUGpic16_emitcode(";lcall","__gptrput");
+          break;  
+        */
+      default:
+       assert(0);
+    }   
+
+
+    pic16_mov2w(AOP(right), offset++);
+  }
+
+  /* last last was not complete */
+  if (rLen)   {
+    /* save the byte & read byte */
+    switch (p_type) {
+      case POINTER:
+       //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
+       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
        break;
-       
-      case GPOINTER:
-       DEBUGpic16_emitcode(";lcall","__gptrput");
-       break;                  
-*/
+
+       /*
+          case FPOINTER:
+          pic16_emitcode ("mov","b,a");
+          pic16_emitcode("movx","a,@dptr");
+          break;
+
+          case GPOINTER:
+          pic16_emitcode ("push","b");
+          pic16_emitcode ("push","acc");
+          pic16_emitcode ("lcall","__gptrget");
+          pic16_emitcode ("pop","b");
+          break;
+        */
       default:
-        assert(0);
+       assert(0);
     }
-    
-//    pic16_freeAsmop(right, NULL, ic, TRUE);
+    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");
+
+  switch (p_type) {
+
+    case POINTER:
+      pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
+      //       pic16_emitcode("mov","@%s,a",rname);
+      break;
+      /*
+        case FPOINTER:
+        pic16_emitcode("movx","@dptr,a");
+        break;
+
+        case GPOINTER:
+        DEBUGpic16_emitcode(";lcall","__gptrput");
+        break;                 
+       */
+    default:
+      assert(0);
+  }
+
+  //    pic16_freeAsmop(right, NULL, ic, TRUE);
 }
+
 /*-----------------------------------------------------------------*/
 /* genDataPointerSet - remat pointer to data space                 */
 /*-----------------------------------------------------------------*/