* src/pic/gen.c (bitpatternFromVal): fixed for 64-bit machines
[fw/sdcc] / src / pic16 / gen.c
index 6a0d0683019811532b83bb9273cd0e622edfd983..7d58f40030e7aa79666aef838d393bc61b2d5280 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
@@ -249,7 +249,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);   
 
@@ -275,7 +275,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;
@@ -410,7 +410,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 +428,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 +707,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);
@@ -851,14 +852,21 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
     }
     /* if it is in direct space */
     if (IN_DIRSPACE(space)) {
-        sym->aop = aop = newAsmop (AOP_DIR);
-        aop->aopu.aop_dir = sym->rname ;
-        aop->size = getSize(sym->type);
-        DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
-        pic16_allocDirReg( IC_LEFT(ic) );
-        return aop;
-    }
-
+               if(!strcmp(sym->rname, "_WREG")) {
+                       sym->aop = aop = newAsmop (AOP_ACC);
+                       aop->size = getSize(sym->type);         /* should always be 1 */
+                       assert(aop->size == 1);
+                       DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
+                       return (aop);
+               } else {
+                       sym->aop = aop = newAsmop (AOP_DIR);
+               aop->aopu.aop_dir = sym->rname ;
+           aop->size = getSize(sym->type);
+               DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
+                       pic16_allocDirReg( IC_LEFT(ic) );
+                       return (aop);
+               }
+       }
 
     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
         sym->aop = aop = newAsmop (AOP_DIR);
@@ -920,7 +928,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
 /*-----------------------------------------------------------------*/
 /* aopForRemat - rematerialzes an object                           */
 /*-----------------------------------------------------------------*/
-static asmop *aopForRemat (operand *op) // x symbol *sym)
+static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
 {
   symbol *sym = OP_SYMBOL(op);
   operand *refop;
@@ -938,6 +946,7 @@ static asmop *aopForRemat (operand *op) // x symbol *sym)
                DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
        }
 
+//    if(!result)              /* fixme-vr */
        for (;;) {
                oldic = ic;
 
@@ -1225,7 +1234,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
         /* rematerialize it NOW */
         if (sym->remat) {
 
-            sym->aop = op->aop = aop = aopForRemat (op);
+            sym->aop = op->aop = aop = aopForRemat (op, result);
 //            aop->size = getSize(sym->type);
 //         DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
             return;
@@ -1280,6 +1289,10 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
 #endif
 
        sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
+       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
+           /* Don't reuse the new aop */
+           sym->usl.spillLoc->aop = NULL;
+       }
        //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
        if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
          aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
@@ -1403,10 +1416,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;
           }
@@ -1581,7 +1605,7 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
 //         return "acc";
         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
           aop->type = AOP_ACC;
-          return Safe_strdup("WREG");
+          return Safe_strdup("_WREG");
         }
         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
        
@@ -1658,7 +1682,7 @@ int _TempReg_lock = 0;
 /*-----------------------------------------------------------------*/
 pCodeOp *pic16_popGetTempReg(int lock)
 {
-  pCodeOp *pcop;
+  pCodeOp *pcop=NULL;
   symbol *cfunc;
 
 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
@@ -1671,6 +1695,34 @@ pCodeOp *pic16_popGetTempReg(int lock)
     cfunc = currFunc;
     currFunc = NULL;
 
+#if 0
+       {
+         regs *rr;
+         int i;
+
+               /* this code might seem better but it does the *same* job with
+                * the old code, it all depends on ralloc.c to get a free/unused
+                * register */
+        
+               i=0;
+               while(i < pic16_nRegs) {
+                       rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
+                       fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
+                       if((!rr || (rr && rr->isFree))
+                               && !bitVectBitValue(cfunc->regsUsed, i)) {
+                               pcop = pic16_newpCodeOpReg( i );
+                               PCOR(pcop)->r->wasUsed = 1;
+                               PCOR(pcop)->r->isFree = 0;
+                               break;
+                       }
+                       i++;
+               }
+
+               if(pcop) {
+                       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
+               }
+       }
+#else
     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
       PCOR(pcop)->r->wasUsed=1;
@@ -1679,6 +1731,7 @@ pCodeOp *pic16_popGetTempReg(int lock)
       /* push value on stack */
       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
     }
+#endif
 
     currFunc = cfunc;
 
@@ -1785,7 +1838,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);
@@ -1832,6 +1885,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    */
 /*-----------------------------------------------------------------*/
@@ -1889,6 +1948,7 @@ static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand
   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
 
   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
+//  PCOR(pcop)->r->wasUsed = 1;
 
   /* make sure that register doesn't exist,
    * and operand isn't NULL
@@ -1900,7 +1960,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;
@@ -1913,11 +1973,14 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx)
   pCodeOp *pcop;
 
 //     DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
-
+//     fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
+       
        pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
        PCOR(pcop)->rIdx = rIdx;
        PCOR(pcop)->r = pic16_regWithIdx(rIdx);
-
+       if(!PCOR(pcop)->r)
+               PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
+               
        PCOR(pcop)->r->isFree = 0;
        PCOR(pcop)->r->wasUsed = 1;
 
@@ -1990,13 +2053,13 @@ pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
 /*-----------------------------------------------------------------*/
 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
 {
-  //char *s = buffer ;
-  char *rs;
+//  char *s = buffer ;
+//  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)
@@ -2004,69 +2067,65 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
 
     /* depending on type */
     switch (aop->type) {
-       
-    case AOP_R0:
-    case AOP_R1:
-    case AOP_DPTR:
-    case AOP_DPTR2:
-        DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
-        fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
-       assert( 0 );
-       return NULL;
-
-
-    case AOP_FSR0:
-    case AOP_FSR2:
-      pcop = Safe_calloc(1, sizeof(pCodeOpReg));
-      PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;    /* access PLUSW register */
-      PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
-      PCOR(pcop)->r->wasUsed = 1;
-      PCOR(pcop)->r->isFree = 0;
+               case AOP_R0:
+               case AOP_R1:
+               case AOP_DPTR:
+               case AOP_DPTR2:
+                       DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
+                       fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
+                       assert( 0 );
+                       return NULL;
+
+               case AOP_FSR0:
+               case AOP_FSR2:
+                       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
+                       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
+                       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
+                       PCOR(pcop)->r->wasUsed = 1;
+                       PCOR(pcop)->r->isFree = 0;
       
-      PCOR(pcop)->instance = offset;
-      pcop->type = PCOR(pcop)->r->pc_type;
-      return (pcop);
-
-    case AOP_IMMD:
-      DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
-      return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
-
-    case AOP_STA:
-      /* pCodeOp is already allocated from aopForSym */
-        DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
-        pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
-          
-      return (pcop);
+                       PCOR(pcop)->instance = offset;
+                       pcop->type = PCOR(pcop)->r->pc_type;
+                       return (pcop);
+
+               case AOP_IMMD:
+                       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
+                       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
+
+               case AOP_STA:
+                       /* pCodeOp is already allocated from aopForSym */
+                       DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
+                       pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
+                       return (pcop);
       
-    case AOP_ACC:
-      {
-       int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
+               case AOP_ACC:
+                       {
+                         int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
 
-       fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
+                               fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
 
-       DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
+                               DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
        
-       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
-       PCOR(pcop)->rIdx = rIdx;
-       PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
-       PCOR(pcop)->r->wasUsed=1;
-       PCOR(pcop)->r->isFree=0;
+                               pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+                               PCOR(pcop)->rIdx = rIdx;
+                               PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
+                               PCOR(pcop)->r->wasUsed=1;
+                               PCOR(pcop)->r->isFree=0;
 
-       PCOR(pcop)->instance = offset;
-       pcop->type = PCOR(pcop)->r->pc_type;
-//     rs = aop->aopu.aop_reg[offset]->name;
-//     DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
-       return pcop;
+                               PCOR(pcop)->instance = offset;
+                               pcop->type = PCOR(pcop)->r->pc_type;
+//                             DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
+                               return pcop;
 
 
 //     return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
 
 //     assert( 0 );
-      }
+                       }
        
     case AOP_DIR:
-      DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
+      DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
        
 #if 0
@@ -2086,7 +2145,7 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
        pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
 //     pcop->type = PO_GPR_REGISTER;
        PCOR(pcop)->rIdx = rIdx;
-       PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
+       PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
        PCOR(pcop)->r->wasUsed=1;
        PCOR(pcop)->r->isFree=0;
 
@@ -2094,8 +2153,8 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
        pcop->type = PCOR(pcop)->r->pc_type;
        
        DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
-       rs = aop->aopu.aop_reg[offset]->name;
-       DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
+//     rs = aop->aopu.aop_reg[offset]->name;
+//     DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
        return pcop;
       }
 
@@ -2487,6 +2546,8 @@ void pushaop(asmop *aop, int offset)
 {
   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
+  if(_G.resDirect)return;
+  
   if(is_LitAOp(aop)) {
     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
@@ -3308,8 +3369,8 @@ static void genCall (iCode *ic)
                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
 
 //                pushaop(AOP(IC_LEFT(sic)), size);
-                pic16_mov2w (AOP(IC_LEFT(sic)), size);
-
+                               pic16_mov2w( AOP(IC_LEFT(sic)), size );
+                               
                 if(!_G.resDirect)
                   pushw();
               }
@@ -3745,22 +3806,41 @@ static void genFunction (iCode *ic)
 
         /* if any registers used */
         if (sym->regsUsed) {
-          /* save the registers used */
-          DEBUGpic16_emitcode("; **", "Saving used registers in stack");
-          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
-          for ( i = 0 ; i < sym->regsUsed->size ; i++) {
-            if (bitVectBitValue(sym->regsUsed,i)) {
-              pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
-              _G.nRegsSaved++;
-
-              if(!pic16_regWithIdx(i)->wasUsed) {
-                fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
-                              __FILE__, __LINE__, pic16_regWithIdx(i)->name);
-                pic16_regWithIdx(i)->wasUsed = 1;
+                 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
+
+          if(!xinst) {
+            /* save the registers used */
+            DEBUGpic16_emitcode("; **", "Saving used registers in stack");
+            for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+              if (bitVectBitValue(sym->regsUsed,i)) {
+#if 0
+               fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
+#endif
+                pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
+                _G.nRegsSaved++;
+
+                if(!pic16_regWithIdx(i)->wasUsed) {
+                  fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
+                                __FILE__, __LINE__, pic16_regWithIdx(i)->name);
+                  pic16_regWithIdx(i)->wasUsed = 1;
+                }
               }
             }
+          } else {
+            
+            /* xinst */
+            DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
+            for(i=0;i<sym->regsUsed->size;i++) {
+              if(bitVectBitValue(sym->regsUsed, i)) {
+                _G.nRegsSaved++;
+              }
+            }
+                        
+//            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
           }
+
           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
+
         }
     }
        
@@ -9351,7 +9431,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;
@@ -9956,7 +10036,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);
@@ -10453,10 +10533,21 @@ static void genRightShift (iCode *ic) {
 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
 void pic16_loadFSR0(operand *op, int lit)
 {
-  if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
-    pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+  if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
+    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 (!OP_SYMBOL(op)->remat);
+    assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
     // set up FSR0 with address of result
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
@@ -12470,8 +12561,16 @@ static void genAssign (iCode *ic)
     } else {
       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-      if(!_G.resDirect)                /* use this aopForSym feature */
-        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++;