* src/pic16/{pcode.h,genarith.c}:
[fw/sdcc] / src / pic16 / gen.c
index 55810a463ba86af169aa2f7efc7750cbc07c9253..b1f315daaac3dde4ad950c5b674b4bb78f719cc7 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
@@ -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);
@@ -1288,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, 
@@ -1411,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;
           }
@@ -1979,17 +1995,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);
 }
 
@@ -2001,32 +2008,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);
 }
@@ -3757,9 +3751,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));
       }
     }
 
@@ -3912,9 +3906,9 @@ 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 ));
       }
     }
 
@@ -3996,15 +3990,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));
-  }
 }
 
 /*-----------------------------------------------------------------*/