* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[fw/sdcc] / src / pic16 / gen.c
index d2c7f0363d811bc6bd04037e712be068cd1db0eb..c03145c48b829e10b2cd956c8bf09602c261e20b 100644 (file)
@@ -6,8 +6,8 @@
   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,2005)
-  Bug Fixes  -  Raphael Neider rneider@web.de (2004,2005)
+             -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
+  Bug Fixes  -  Raphael Neider <rneider AT 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
@@ -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;
@@ -249,7 +251,7 @@ void pic16_emitpcomment (char *fmt, ...)
 {
     va_list ap;
     char lb[INITIAL_INLINEASM];  
-    unsigned char *lbp = lb;
+    unsigned char *lbp = (unsigned char *)lb;
 
     va_start(ap,fmt);   
 
@@ -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);
@@ -275,7 +278,7 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
 {
     va_list ap;
     char lb[INITIAL_INLINEASM];  
-    unsigned char *lbp = lb;
+    unsigned char *lbp = (unsigned char *)lb;
 
     if(!pic16_debug_verbose)
       return;
@@ -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);
 
@@ -410,7 +415,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
     bool fsr0iu = FALSE, fsr0ou;
     bool fsr2iu = FALSE, fsr2ou;
     
-    fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
+    //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
 
     
     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
@@ -428,7 +433,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
        ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
        (*aopp)->type = AOP_FSR0;
 
-       fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
+       //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
        
       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
     }
@@ -707,6 +712,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
           /* if SEND do the send here */
           _G.resDirect = 1;
         } else {
+//               debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
           for(i=0;i<aop->size;i++) {
             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
@@ -949,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));
@@ -1287,19 +1295,30 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
                            sym->rname, sym->usl.spillLoc->offset);
 #endif
 
-       sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
        //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
        if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
+         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
          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__);
+       } else if (getSize(sym->type) <= 1) {
+         //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
          pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
          assert (getSize(sym->type) <= 1);
+         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
          aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
+       } else {
+         /* We need some kind of dummy area for getSize(sym->type) byte,
+          * use WREG for all storage locations.
+          * XXX: This only works if we are implementing a `dummy read',
+          *      the stored value will not be retrievable...
+          *      See #1503234 for a case requiring this. */
+         sym->aop = op->aop = aop = newAsmop(AOP_REG);
+         aop->size = getSize(sym->type);
+         for ( i = 0 ; i < aop->size ;i++)
+           aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
        }
-        aop->size = getSize(sym->type);
+       aop->size = getSize(sym->type);
 
         return;
     }
@@ -1411,10 +1430,21 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
                 for(i=0;i<aop->size;i++) {
                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
 
-                  if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
+                  if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
+//                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
+                  }
                 }
+                
+                {
+                  regs *sr;
                   
+                    _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
+                    for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
+                      pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
+                      deleteSetItem( &_G.sregsAllocSet, sr );
+                    }
+                }
               }
               _G.resDirect = 0;
           }
@@ -1822,7 +1852,7 @@ void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
 /*-----------------------------------------------------------------*/
 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
 /*-----------------------------------------------------------------*/
-pCodeOp *pic16_popGetLabel(unsigned int key)
+pCodeOp *pic16_popGetLabel(int key)
 {
 
   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
@@ -1869,6 +1899,12 @@ pCodeOp *pic16_popGetLit(int lit)
   return pic16_newpCodeOpLit(lit);
 }
 
+/* Allow for 12 bit literals (LFSR x, <here!>). */
+pCodeOp *pic16_popGetLit12(int lit)
+{
+  return pic16_newpCodeOpLit12(lit);
+}
+
 /*-----------------------------------------------------------------*/
 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
 /*-----------------------------------------------------------------*/
@@ -1938,7 +1974,7 @@ static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand
 //             __FUNCTION__, __LINE__, str, size, offset);
 
     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
-    fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
+    //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
 
   }
   PCOR(pcop)->instance = offset;
@@ -1973,17 +2009,8 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx)
 /*---------------------------------------------------------------------------------*/
 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
 {
-  pCodeOpReg2 *pcop2;
-  pCodeOp *temp;
-  
-       pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
-
-       /* comment the following check, so errors to throw up */
-//     if(!pcop2)return NULL;
-
-       temp = pic16_popGet(aop_dst, offset);
-       pcop2->pcop2 = temp;
-       
+  pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
+       pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
   return PCOP(pcop2);
 }
 
@@ -1995,32 +2022,19 @@ pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
 /*--------------------------------------------------------------------------------.-*/
 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
 {
-  pCodeOpReg2 *pcop2;
-       pcop2 = (pCodeOpReg2 *)src;
-       pcop2->pcop2 = dst;
-       
-       return PCOP(pcop2);
+  pCodeOp2 *pcop2;
+  pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
+  return PCOP(pcop2);
 }
 
-
-
 /*---------------------------------------------------------------------------------*/
 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
 /*                     movff instruction                                           */
 /*---------------------------------------------------------------------------------*/
 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
 {
-  pCodeOpReg2 *pcop2;
-
-       if(!noalloc) {
-               pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
-               pcop2->pcop2 = pic16_popCopyReg(dst);
-       } else {
-               /* the pCodeOp may be already allocated */
-               pcop2 = (pCodeOpReg2 *)(src);
-               pcop2->pcop2 = (pCodeOp *)(dst);
-       }
+  pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
+       pic16_popCopyReg(src), pic16_popCopyReg(dst) );
 
   return PCOP(pcop2);
 }
@@ -2035,9 +2049,9 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
 //  char *rs;
   pCodeOp *pcop;
 
-       FENTRY2;
-               /* offset is greater than
-                * size then zero */
+    FENTRY2;
+    
+      /* offset is greater than size then zero */
 
 //    if (offset > (aop->size - 1) &&
 //        aop->type != AOP_LIT)
@@ -2115,7 +2129,9 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
     case AOP_REG:
       {
        int rIdx;
-       assert (aop && aop->aopu.aop_reg[offset] != NULL);
+
+//     debugf2("aop = %p\toffset = %d\n", aop, offset);
+//     assert (aop && aop->aopu.aop_reg[offset] != NULL);
        rIdx = aop->aopu.aop_reg[offset]->rIdx;
 
        DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
@@ -2490,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();
     
@@ -2981,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;
@@ -3000,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.
@@ -3384,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))));
@@ -3531,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))));
@@ -3569,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   */
@@ -3681,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));
 
@@ -3731,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);
     }
@@ -3751,9 +3779,9 @@ static void genFunction (iCode *ic)
           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
 
-        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
         if(STACK_MODEL_LARGE)
           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
+        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
       }
     }
 
@@ -3906,15 +3934,17 @@ static void genEndFunction (iCode *ic)
         || FUNC_HASSTACKPARM(sym->etype)
         ) {
         /* restore stack frame */
+        pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
         if(STACK_MODEL_LARGE)
           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
-        pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
       }
     }
 
     _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 ));
@@ -3971,7 +4001,7 @@ void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
 {
   unsigned long lit=1;
   operand *op;
-
+  
     op = IC_LEFT(ic);
   
     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
@@ -3990,15 +4020,28 @@ void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
       }
     }
 
-    if(is_LitOp(op)) {
-      pic16_movLit2f(dest, lit);
+    if (AOP_TYPE(op) == AOP_LIT) {
+      /* FIXME: broken for
+       *   char __at(0x456) foo;
+       *   return &foo;
+       * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
+      pic16_movLit2f(dest, (lit >> (8ul*offset)));
+    } else if (AOP_TYPE(op) == AOP_PCODE
+               && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
+      /* char *s= "aaa"; return s; */
+      /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
+       *      that the generic pointer is interpreted correctly
+       *      as referring to __code space, but this is fragile! */
+      pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
+      /* XXX: should check that dest != WREG */
+      pic16_emitpcode(POC_MOVWF, dest);
     } else {
       if(dest->type == PO_WREG && (offset == 0)) {
-        pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
-      return;
+       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
+       return;
+      }
+      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
     }
-    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
-  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -4194,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                          */
 /*-----------------------------------------------------------------*/
@@ -4233,7 +4277,9 @@ static void genMultOneWord (operand *left,
        
   pic16_genMult16X16_16(left, right,result);
 }
+#endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genMultOneLong : 32 bit multiplication                          */
 /*-----------------------------------------------------------------*/
@@ -4270,6 +4316,7 @@ static void genMultOneLong (operand *left,
        
   pic16_genMult32X32_32(left, right,result);
 }
+#endif
 
 
 
@@ -4305,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) {
@@ -4318,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.");
 
 
@@ -4332,6 +4384,7 @@ release :
        pic16_freeAsmop(result,NULL,ic,TRUE); 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genDivbits :- division of bits                                  */
 /*-----------------------------------------------------------------*/
@@ -4501,6 +4554,7 @@ static void genDivOneByte (operand *left,
         pic16_aopPut(AOP(result),"a",offset++);
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genDiv - generates code for division                            */
@@ -4510,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
@@ -4524,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 &&
@@ -4538,6 +4797,7 @@ static void genDiv (iCode *ic)
         genDivOneByte(left,right,result);
         goto release ;
     }
+#endif
 
     /* should have been converted to function call */
     assert(0);
@@ -4547,6 +4807,7 @@ release :
     pic16_freeAsmop(result,NULL,ic,TRUE); 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genModbits :- modulus of bits                                   */
 /*-----------------------------------------------------------------*/
@@ -4646,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);  
@@ -4685,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
 }
 
 /*-----------------------------------------------------------------*/
@@ -6025,7 +6291,7 @@ static void genCmp (operand *left, operand *right,
         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
         
         werror(W_POSSBUG2, __FILE__, __LINE__);
-        exit(-1);
+        exit(EXIT_FAILURE);
     }
     
     /* if literal is on the right then swap with left */
@@ -7671,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);
@@ -7976,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);
@@ -9065,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;
 
@@ -9082,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));
     }
@@ -9409,7 +9679,7 @@ void pic16_genLeftShiftLiteral (operand *left,
                                  operand *result,
                                  iCode *ic)
 {    
-    int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
+    int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
     int size;
 
     FENTRY;
@@ -10014,7 +10284,7 @@ static void genRightShiftLiteral (operand *left,
                                   iCode *ic,
                                   int sign)
 {    
-  int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
+  int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
   int lsize,res_size;
 
   pic16_freeAsmop(right,NULL,ic,TRUE);
@@ -10512,7 +10782,18 @@ static void genRightShift (iCode *ic) {
 void pic16_loadFSR0(operand *op, int lit)
 {
   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
-    pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+    if (AOP_TYPE(op) == AOP_LIT) {
+      /* handle 12 bit integers correctly */
+      unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
+      if ((val & 0x0fff) != val) {
+        fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
+               val, (val & 0x0fff) );
+       val &= 0x0fff;
+      }
+      pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
+    } else {
+      pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+    }
   } else {
     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
     // set up FSR0 with address of result
@@ -10684,9 +10965,9 @@ static void genUnpackBits (operand *result, operand *left, char *rname, int ptyp
     return ;
   }
 
-  fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
+  fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
-  exit(-1);
+  exit(EXIT_FAILURE);
 
   return ;
 }
@@ -11183,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;
     }
@@ -11440,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)
       {
@@ -11475,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)))
@@ -11493,7 +11779,7 @@ static void genPackBits (sym_link    *etype , operand *result,
 #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);
+  exit(EXIT_FAILURE);
 #endif
 
 
@@ -11620,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);
 }
@@ -12501,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);
@@ -12987,10 +13262,13 @@ static void genCast (iCode *ic)
                if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
                        pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
                        pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
-                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
-                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
-                       if(AOP_SIZE(result) <2)
-                               fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
+
+                       if(AOP_SIZE(result) < 2) {
+                         fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
+                        } else {
+                          pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
+                          pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
+                        }
                } else {
                        /* if they in different places then copy */
                        size = AOP_SIZE(result);
@@ -13272,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);
@@ -13354,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
@@ -13566,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"));