* src/pic16/gen.c (genCast): fixed typo
[fw/sdcc] / src / pic16 / gen.c
index 2d4bfe00fe353bfedefa20cb16d0a7756b622c10..7f9dbe233b1fe782e292a873fe6e4482ede89c58 100644 (file)
@@ -47,6 +47,7 @@
 #include "genutils.h"
 #include "device.h"
 #include "main.h"
+#include "glue.h"
 
 /* Set the following to 1 to enable the slower/bigger
  * but more robust generic shifting routine (which also
 /* Wrapper to execute `code' at most once. */
 #define PERFORM_ONCE(id,code)  do { static char id = 0; if (!id) { id = 1; code } } while (0)
 
+void pic16_genMult8X8_n (operand *, operand *,operand *);
+#if 0
 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 *);
 void pic16_genMult16X16_16(operand *, operand *, operand *);
 void pic16_genMult32X32_32(operand *, operand *, operand *);
+#endif
 pCode *pic16_AssembleLine(char *line, int peeps);
 extern void pic16_printpBlock(FILE *of, pBlock *pb);
 static asmop *newAsmop (short type);
@@ -110,7 +113,6 @@ static int GpsuedoStkPtr=0;
 
 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
 
-unsigned int pic16aopLiteral (value *val, int offset);
 const char *pic16_AopType(short type);
 static iCode *ifxForOp ( operand *op, iCode *ic );
 
@@ -180,7 +182,7 @@ static struct {
 
 extern int pic16_ptrRegReq ;
 extern int pic16_nRegs;
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
 //static void saverbank (int, iCode *,bool);
 
 static lineNode *lineHead = NULL;
@@ -264,6 +266,7 @@ void pic16_emitpcomment (char *fmt, ...)
                     (lineHead = newLineNode(lb)));
     lineCurr->isInline = _G.inLine;
     lineCurr->isDebug  = _G.debugLine;
+    lineCurr->isComment = 1;
 
     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
     va_end(ap);
@@ -376,6 +379,8 @@ void pic16_emitcode (char *inst,char *fmt, ...)
                     (lineHead = newLineNode(lb)));
     lineCurr->isInline = _G.inLine;
     lineCurr->isDebug  = _G.debugLine;
+    lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
+    lineCurr->isComment = (*lbp == ';');
 
 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
 
@@ -950,7 +955,9 @@ static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
        for (;;) {
                oldic = ic;
 
-//             pic16_emitpcomment("ic: %s\n", printILine(ic));
+//              chat *iLine = printILine(ic);
+//             pic16_emitpcomment("ic: %s\n", iLine);
+//              dbuf_free(iLine);
        
                if (ic->op == '+') {
                        val += (int) operandLitValue(IC_RIGHT(ic));
@@ -2499,7 +2506,12 @@ void pic16_testStackOverflow(void)
 void pic16_pushpCodeOp(pCodeOp *pcop)
 {
 //     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
+  if (pcop->type == PO_LITERAL) {
+    pic16_emitpcode(POC_MOVLW, pcop);
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
+  } else {
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
+  }
   if(pic16_options.gstack)
     pic16_testStackOverflow();
     
@@ -2990,7 +3002,7 @@ void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
 /* assignResultValue - assign results to oper, rescall==1 is       */
 /*                     called from genCall() or genPcall()         */
 /*-----------------------------------------------------------------*/
-static void assignResultValue(operand * oper, int rescall)
+static void assignResultValue(operand * oper, int res_size, int rescall)
 {
   int size = AOP_SIZE(oper);
   int offset=0;
@@ -3009,20 +3021,22 @@ static void assignResultValue(operand * oper, int rescall)
         /* 8-bits, result in WREG */
         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
                        
-        if(size>1) {
+        if(size > 1 && res_size > 1) {
          /* 16-bits, result in PRODL:WREG */
          pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
        }
                        
-       if(size>2) {
+       if(size > 2 && res_size > 2) {
          /* 24-bits, result in PRODH:PRODL:WREG */
          pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
        }
                        
-       if(size>3) {
+       if(size > 3 && res_size > 3) {
          /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
          pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
        }
+
+       pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
       
       } else {
         /* >32-bits, result on stack, and FSR0 points to beginning.
@@ -3393,7 +3407,11 @@ static void genCall (iCode *ic)
       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
       _G.accInUse--;
 
-      assignResultValue(IC_RESULT(ic), 1);
+      /* Must not assign an 8-bit result to a 16-bit variable;
+       * this would use (used...) the uninitialized PRODL! */
+      /* FIXME: Need a proper way to obtain size of function result type,
+       * OP_SYM_ETYPE does not work: it dereferences pointer types! */
+      assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
 
       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
@@ -3540,7 +3558,9 @@ static void genPcall (iCode *ic)
       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
       _G.accInUse--;
 
-      assignResultValue(IC_RESULT(ic), 1);
+      /* FIXME: Need proper way to obtain the function result's type.
+       * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
+      assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
 
       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
@@ -3578,12 +3598,6 @@ static int resultRemat (iCode *ic)
   return 0;
 }
 
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
 #if 0
 /*-----------------------------------------------------------------*/
 /* inExcludeList - return 1 if the string is in exclude Reg list   */
@@ -3690,6 +3704,9 @@ static void genFunction (iCode *ic)
     pic16_emitcode(";"," function %s",sym->name);
     pic16_emitcode(";","-----------------------------------------");
 
+    /* prevent this symbol from being emitted as 'extern' */
+    pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
+
     pic16_emitcode("","%s:",sym->rname);
     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
 
@@ -3740,6 +3757,8 @@ static void genFunction (iCode *ic)
         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
+        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
+        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
         
 //        pic16_pBlockConvert2ISR(pb);
     }
@@ -3924,6 +3943,8 @@ static void genEndFunction (iCode *ic)
     _G.useWreg = 0;
 
     if (IFFUNC_ISISR(sym->type)) {
+      pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
+      pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
@@ -4216,9 +4237,10 @@ static void genMultOneByte (operand *left,
                                        pic16_aopGet(AOP(result),0,FALSE,FALSE));
        }
        
-       pic16_genMult8X8_8 (left, right,result);
+       pic16_genMult8X8_n (left, right,result);
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genMultOneWord : 16 bit multiplication                          */
 /*-----------------------------------------------------------------*/
@@ -4255,7 +4277,9 @@ static void genMultOneWord (operand *left,
        
   pic16_genMult16X16_16(left, right,result);
 }
+#endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genMultOneLong : 32 bit multiplication                          */
 /*-----------------------------------------------------------------*/
@@ -4292,6 +4316,7 @@ static void genMultOneLong (operand *left,
        
   pic16_genMult32X32_32(left, right,result);
 }
+#endif
 
 
 
@@ -4327,6 +4352,7 @@ static void genMult (iCode *ic)
          goto release ;
        }
 
+#if 0
        /* if both are of size == 2 */
        if(AOP_SIZE(left) == 2
                && AOP_SIZE(right) == 2) {
@@ -4340,7 +4366,11 @@ static void genMult (iCode *ic)
                genMultOneLong(left, right, result);
          goto release;
        }
-       
+#endif
+
+       fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
+       assert( !"Multiplication should have been transformed into function call!" );
+
        pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
 
 
@@ -4354,6 +4384,7 @@ release :
        pic16_freeAsmop(result,NULL,ic,TRUE); 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genDivbits :- division of bits                                  */
 /*-----------------------------------------------------------------*/
@@ -4523,6 +4554,7 @@ static void genDivOneByte (operand *left,
         pic16_aopPut(AOP(result),"a",offset++);
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genDiv - generates code for division                            */
@@ -4532,8 +4564,12 @@ static void genDiv (iCode *ic)
     operand *left = IC_LEFT(ic);
     operand *right = IC_RIGHT(ic);
     operand *result= IC_RESULT(ic);   
-
-
+    int negated = 0;
+    int leftVal = 0, rightVal = 0;
+    int signedLits = 0;
+    char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
+    int op = 0;
+    
        /* Division is a very lengthy algorithm, so it is better
         * to call support routines than inlining algorithm.
         * Division functions written here just in case someone
@@ -4546,6 +4582,207 @@ static void genDiv (iCode *ic)
     pic16_aopOp (right,ic,FALSE);
     pic16_aopOp (result,ic,TRUE);
 
+    if (ic->op == '/')
+      op = 0;
+    else if (ic->op == '%')
+      op = 1;
+    else
+      assert( !"invalid operation requested in genDivMod" );
+
+    /* get literal values */
+    if (IS_VALOP(left)) {
+      leftVal = (int)floatFromVal( OP_VALUE(left) );
+      assert( leftVal >= -128 && leftVal < 256 );
+      if (leftVal < 0) { signedLits++; }
+    }
+    if (IS_VALOP(right)) {
+      rightVal = (int)floatFromVal( OP_VALUE(right) );
+      assert( rightVal >= -128 && rightVal < 256 );
+      if (rightVal < 0) { signedLits++; }
+    }
+
+    /* We should only come here to convert all
+     * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
+     * with exactly one operand being s8_t into
+     * u8_t x u8_t -> u8_t. All other cases should have been
+     * turned into calls to support routines beforehand... */
+    if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
+       && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
+    {
+      if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
+         && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
+      {
+       /* Both operands are signed or negative, use _divschar
+        * instead of _divuchar */
+       pushaop(AOP(right), 0);
+       pushaop(AOP(left), 0);
+
+       /* call _divschar */
+       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
+
+       {
+         symbol *sym;
+         sym = newSymbol( functions[op][0], 0 );
+         sym->used++;
+         strcpy(sym->rname, functions[op][0]);
+         checkAddSym(&externs, sym);
+       }
+
+       /* assign result */
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+       if (AOP_SIZE(result) > 1)
+       {
+         pic16_emitpcode(POC_MOVFF,
+             pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
+               pic16_popGet(AOP(result), 1)));
+         /* sign extend */
+         pic16_addSign(result, 2, 1);
+       }
+
+       /* clean up stack */
+       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+
+       goto release;
+      }
+      
+      /* push right operand */
+      if (IS_VALOP(right)) {
+       if (rightVal < 0) {
+         pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
+         negated++;
+       } else {
+         pushaop(AOP(right), 0);
+       }
+      } else if (!IS_UNSIGNED(operandType(right))) {
+       pic16_mov2w(AOP(right), 0);
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+       pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
+       negated++;
+      } else {
+       pushaop(AOP(right), 0);
+      }
+
+      /* push left operand */
+      if (IS_VALOP(left)) {
+       if (leftVal < 0) {
+         pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
+         negated++;
+       } else {
+         pushaop(AOP(left), 0);
+       }
+      } else if (!IS_UNSIGNED(operandType(left))) {
+       pic16_mov2w(AOP(left),0);
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+       pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
+       negated++;
+      } else {
+       pushaop(AOP(left), 0);
+      }
+      
+      /* call _divuchar */
+      pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
+
+      {
+       symbol *sym;
+       sym = newSymbol( functions[op][1], 0 );
+       sym->used++;
+       strcpy(sym->rname, functions[op][1]);
+       checkAddSym(&externs, sym);
+      }
+
+      /* Revert negation(s) from above.
+       * This is inefficient: if both operands are negative, this
+       * should not touch WREG. However, determining that exactly
+       * one operand was negated costs at least 3 instructions,
+       * so there is nothing to be gained here, is there?
+       *
+       * I negate WREG because either operand might share registers with
+       * result, so assigning first might destroy an operand. */
+      
+      /* For the modulus operator, (a/b)*b == a shall hold.
+       * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
+       *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
+       *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
+       *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
+       * Only invert the result if the left operand is negative (sigh).
+       */
+      if (AOP_SIZE(result) <= 1 || !negated)
+      {
+       if (ic->op == '/')
+       {
+         if (IS_VALOP(right)) {
+           if (rightVal < 0) {
+             /* we negated this operand above */
+             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+           }
+         } else if (!IS_UNSIGNED(operandType(right))) {
+           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+         }
+       }
+
+       if (IS_VALOP(left)) {
+         if (leftVal < 0) {
+           /* we negated this operand above */
+           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+         }
+       } else if (!IS_UNSIGNED(operandType(left))) {
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+       }
+
+       /* Move result to destination. */
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+
+       /* Zero-extend:  no operand was signed (or result is just a byte). */
+       pic16_addSign(result, 1, 0);
+      } else {
+       assert( AOP_SIZE(result) > 1 );
+       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+       if (ic->op == '/')
+       {
+         if (IS_VALOP(right)) {
+           if (rightVal < 0) {
+             /* we negated this operand above */
+             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+           }
+         } else if (!IS_UNSIGNED(operandType(right))) {
+           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+         }
+       }
+
+       if (IS_VALOP(left)) {
+         if (leftVal < 0) {
+           /* we negated this operand above */
+           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+         }
+       } else if (!IS_UNSIGNED(operandType(left))) {
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+         pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+       }
+
+       /* Move result to destination. */
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+
+       /* Negate result if required. */
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
+       pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
+
+       /* Sign-extend. */
+       pic16_addSign(result, 2, 1);
+      }
+
+      /* clean up stack */
+      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+      goto release;
+    }
+
+#if 0
     /* special cases first */
     /* both are bits */
     if (AOP_TYPE(left) == AOP_CRY &&
@@ -4560,6 +4797,7 @@ static void genDiv (iCode *ic)
         genDivOneByte(left,right,result);
         goto release ;
     }
+#endif
 
     /* should have been converted to function call */
     assert(0);
@@ -4569,6 +4807,7 @@ release :
     pic16_freeAsmop(result,NULL,ic,TRUE); 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genModbits :- modulus of bits                                   */
 /*-----------------------------------------------------------------*/
@@ -4668,12 +4907,16 @@ static void genModOneByte (operand *left,
     pic16_aopPut(AOP(result),"b",0);
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genMod - generates code for division                            */
 /*-----------------------------------------------------------------*/
 static void genMod (iCode *ic)
 {
+  /* Task deferred to genDiv */
+  genDiv(ic);
+#if 0
   operand *left = IC_LEFT(ic);
   operand *right = IC_RIGHT(ic);
   operand *result= IC_RESULT(ic);  
@@ -4707,6 +4950,7 @@ release :
     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
     pic16_freeAsmop(result,NULL,ic,TRUE); 
+#endif
 }
 
 /*-----------------------------------------------------------------*/
@@ -7693,6 +7937,7 @@ static void genOr (iCode *ic, iCode *ifx)
     unsigned long lit = 0L;
 
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    FENTRY;
 
     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
@@ -7998,6 +8243,7 @@ static void genXor (iCode *ic, iCode *ifx)
   unsigned long lit = 0L;
 
   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  FENTRY;
 
   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
@@ -9087,8 +9333,9 @@ static void shiftR2Left2Result (operand *left, int offl,
   case 1:
   case 2:
   case 3:
+    /* obtain sign from left operand */
     if(sign)
-      pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
     else
       emitCLRC;
 
@@ -9104,9 +9351,10 @@ static void shiftR2Left2Result (operand *left, int offl,
 
     while(--shCount) {
       if(sign)
-               pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
+       /* now get sign from already assigned result (avoid BANKSEL) */
+       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
       else
-               emitCLRC;
+       emitCLRC;
       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
     }
@@ -11216,7 +11464,7 @@ static void genGenPointerGet (operand *left,
       pic16_mov2w(AOP(left), 2);
       pic16_callGenericPointerRW(0, size);
       
-      assignResultValue(result, 1);
+      assignResultValue(result, size, 1);
       
       goto release;
     }
@@ -11473,7 +11721,7 @@ static void genPackBits (sym_link    *etype , operand *result,
       || SPEC_BLEN(etype) <= 8 )  {
     int fsr0_setup = 0;
 
-    if (blen != 8 || bstr != 0) {
+    if (blen != 8 || (bstr % 8) != 0) {
       // we need to combine the value with the old value
       if(!shifted_and_masked)
       {
@@ -11508,7 +11756,12 @@ static void genPackBits (sym_link    *etype , operand *result,
         if (lit != 0)
          pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
       }
-    } // if (blen != 8 || bstr != 0)
+    } else { // if (blen == 8 && (bstr % 8) == 0)
+       if (shifted_and_masked) {
+           // move right (literal) to WREG (only case where right is not yet in WREG)
+           pic16_mov2w(AOP(right), (bstr / 8));
+       }
+    }
 
     /* write new value back */
     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
@@ -11653,29 +11906,15 @@ static void genDataPointerSet(operand *right,
 
     while (size--) {
       if (AOP_TYPE(right) == AOP_LIT) {
-        unsigned int lit;
-
-          if(!IS_FLOAT(operandType( right )))
-            lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-          else {
-            union {
-              unsigned long lit_int;
-              float lit_float;
-            } info;
-       
-              /* take care if literal is a float */
-              info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-              lit = info.lit_int;
-          }
-                    lit = lit >> (8*offset);
-                   pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
-                } else {
-                  pic16_mov2w(AOP(right), offset);
-                  pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
-                }
-               offset++;
-               resoffset++;
-       }
+       unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
+       pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
+      } else {
+       pic16_mov2w(AOP(right), offset);
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
+      }
+      offset++;
+      resoffset++;
+    }
 
     pic16_freeAsmop(right,NULL,ic,TRUE);
 }
@@ -12534,47 +12773,50 @@ static void genAssign (iCode *ic)
     }
 #endif
 
-  know_W=-1;
-  while (size--) {
-    DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
-    if(AOP_TYPE(right) == AOP_LIT) {
-      if(lit&0xff) {
-       if(know_W != (lit&0xff))
-         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
-       know_W = lit&0xff;
-       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
-      } else
-       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+    size = AOP_SIZE(right);
+    if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
+    know_W=-1;
+    while (size--) {
+      DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
+      if(AOP_TYPE(right) == AOP_LIT) {
+       if(lit&0xff) {
+         if(know_W != (lit&0xff))
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
+         know_W = lit&0xff;
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+       } else
+         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
 
-      lit >>= 8;
+       lit >>= 8;
 
-    } else if (AOP_TYPE(right) == AOP_CRY) {
-      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
-      if(offset == 0) {
-        //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
-       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
-       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
-      }
-    } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
+      } else if (AOP_TYPE(right) == AOP_CRY) {
+       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+       if(offset == 0) {
+         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
+         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+       }
+      } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
        pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
        pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
-    } else {
-      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      } else {
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-      if(!_G.resDirect) {                                              /* use this aopForSym feature */
-          if(AOP_TYPE(result) == AOP_ACC) {
-            pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
-          } else
-          if(AOP_TYPE(right) == AOP_ACC) {
-            pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
-          } else {
-            pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
-          }
+       if(!_G.resDirect) {                                             /* use this aopForSym feature */
+         if(AOP_TYPE(result) == AOP_ACC) {
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
+         } else
+           if(AOP_TYPE(right) == AOP_ACC) {
+             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
+           } else {
+             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
+           }
+       }
       }
-    }
-      
+
       offset++;
     }
+    pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
   
 release:
   pic16_freeAsmop (right,NULL,ic,FALSE);
@@ -12933,12 +13175,12 @@ static void genCast (iCode *ic)
              tag = GPTR_TAG_CODE;
            } else if (IS_PTR(rtype)) {
              PERFORM_ONCE(weirdcast,
-             fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
+             fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
              );
              tag = GPTR_TAG_DATA;
            } else {
              PERFORM_ONCE(weirdcast,
-             fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
+             fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
              );
              tag = GPTR_TAG_DATA;
            }
@@ -13308,7 +13550,9 @@ static void genReceive (iCode *ic)
     GpsuedoStkPtr = ic->parmBytes;
 
     /* setting GpsuedoStkPtr has side effects here: */
-    assignResultValue(IC_RESULT(ic), 0);
+    /* FIXME: What's the correct size of the return(ed) value?
+     *        For now, assuming '4' as before... */
+    assignResultValue(IC_RESULT(ic), 4, 0);
   }
 
   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
@@ -13390,11 +13634,12 @@ void genpic16Code (iCode *lic)
       }
        
       if(options.iCodeInAsm) {
-        char *l;
+        char *iLine;
 
           /* insert here code to print iCode as comment */
-          l = Safe_strdup(printILine(ic));
-          pic16_emitpcomment("ic:%d: %s", ic->seq, l);
+          iLine = printILine(ic);
+          pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
+          dbuf_free(iLine);
       }
 
       /* if the result is marked as
@@ -13602,7 +13847,7 @@ void genpic16Code (iCode *lic)
       peepHole (&lineHead);
 
     /* now do the actual printing */
-    printLine (lineHead, codeOutFile);
+    printLine (lineHead, codeOutBuf);
 
 #ifdef PCODE_DEBUG
     DFPRINTF((stderr,"printing pBlock\n\n"));