* device/lib/pic16/configure, device/lib/pic16/configure.ac:
[fw/sdcc] / src / pic16 / gen.c
index 3858e4489d563f25b80752a5170063aafa727730..c298845c2a788c79ed0184921efccba7c7689d3f 100644 (file)
@@ -9,6 +9,7 @@
              -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
   Bug Fixes  -  Borut Razem <borut.razem AT siol.net> (2007)
+  Bug Fixes  -  Mauro Giachero <maurogiachero AT users.sourceforge.net> (2008)
 
   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
 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
 
-/* If you change these, you also have to update the library files
- * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
-#define GPTR_TAG_DATA   0x80
-#define GPTR_TAG_EEPROM 0x40
-#define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
-
 /* Wrapper to execute `code' at most once. */
 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
 
@@ -270,11 +265,17 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
 
 void pic16_emitpLabel(int key)
 {
+  if(key>max_key)
+    max_key = key;
+
   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
 }
 
 void pic16_emitpLabelFORCE(int key)
 {
+  if(key>max_key)
+    max_key = key;
+
   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
 }
 
@@ -2295,7 +2296,7 @@ static void genUminusFloat(operand *op,operand *result)
 /*-----------------------------------------------------------------*/
 static void genUminus (iCode *ic)
 {
-  int size, i;
+  int lsize, rsize, i;
   sym_link *optype, *rtype;
   symbol *label;
   int needLabel=0;
@@ -2330,40 +2331,65 @@ static void genUminus (iCode *ic)
     }
 
     /* otherwise subtract from zero by taking the 2's complement */
-    size = AOP_SIZE(IC_LEFT(ic));
-    assert( size == AOP_SIZE(IC_RESULT(ic)) );
+    lsize = AOP_SIZE(IC_LEFT(ic));
+    rsize = AOP_SIZE(IC_RESULT(ic));
     label = newiTempLabel ( NULL );
 
     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
-      for (i=size-1; i > 0; i--) {
-        pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
+      /* If the result is longer than the operand,
+         store sign extension (0x00 or 0xff) in W */
+      if (rsize > lsize) {
+        pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00));
+        pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_LEFT(ic)), lsize-1), 7));
+        pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF));
+      }
+      for (i = rsize - 1; i > 0; --i) {
+        if (i > lsize - 1) {
+          pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
+        } else {
+          pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_RESULT(ic)), i));
+        } // if
       } // for
-      pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
-      for (i=1; i < size; i++) {
-        if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
-        pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
+      pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_RESULT(ic)), 0));
+      for (i = 1; i < rsize; ++i) {
+        if (i == rsize - 1) {
+          emitSKPNZ;
+        } else {
+          pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
+        }
+        pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)), i));
       } // for
     } else {
-      for (i=size-1; i >= 0; i--) {
+      for (i = min(rsize, lsize) - 1; i >= 0; i--) {
         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
       } // for
-      if (size > 1) {
-        for (i=0; i < size-2; i++) {
+      /* Sign extend if the result is longer than the operand */
+      if (rsize > lsize) {
+        pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00));
+        pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_RESULT(ic)), lsize - 1), 7));
+        pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF));
+        for (i = rsize - 1; i > lsize - 1; --i) {
+          pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
+        } // for
+      } // if
+      if (rsize > 1) {
+        for (i = 0; i < rsize - 2; i++) {
           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
-          pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
+          pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key));
+          needLabel++;
         } // for
-        pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
+        pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), rsize - 2));
       } // if
-      pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
+      pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), rsize - 1));
     }
     if (needLabel)
       pic16_emitpLabel (label->key);
 
 release:
     /* release the aops */
-    pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
-    pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+    pic16_freeAsmop(IC_LEFT(ic), NULL, ic, (RESULTONSTACK(ic) ? 0 : 1));
+    pic16_freeAsmop(IC_RESULT(ic), NULL, ic, TRUE);
 }
 
 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
@@ -5470,7 +5496,7 @@ static void genAnd (iCode *ic, iCode *ifx)
                   if (nonnull)
                     {
                       pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
-                      pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
+                      pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
                     }
                   else
                     {
@@ -5495,7 +5521,7 @@ static void genAnd (iCode *ic, iCode *ifx)
                       if (rIfx.condition)
                         {
                           emitSKPZ;
-                          pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
+                          pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
                         }
                       else
                         {
@@ -5527,7 +5553,7 @@ static void genAnd (iCode *ic, iCode *ifx)
           if (ifx)
             {
               if (emitBra)
-                pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
+                pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
               ifx->generated = 1;
             }
           pic16_emitpLabel (tlbl->key);
@@ -5811,7 +5837,7 @@ static void genOr (iCode *ic, iCode *ifx)
       if (lit)
         {
           if (rIfx.condition)
-            pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
+            pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
           ifx->generated = 1;
         }
       else
@@ -6091,7 +6117,7 @@ static void genXor (iCode *ic, iCode *ifx)
                 {
                   /* rIfx.lbl might be far away... */
                   emitSKPZ;
-                  pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
+                  pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
                 }
               else
                 {
@@ -6119,7 +6145,7 @@ static void genXor (iCode *ic, iCode *ifx)
         {
           if (ifx)
             {
-              pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
+              pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
               ifx->generated = 1;
             }
           pic16_emitpLabel (tlbl->key);
@@ -6141,10 +6167,10 @@ static void genXor (iCode *ic, iCode *ifx)
               if  (t == 0x00L)
                 continue;
               else
-               {
-                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
-                 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
-               }
+                {
+                  pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
+                  pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
+                }
             }
           else
             {
@@ -6376,7 +6402,7 @@ static void genInline (iCode *ic)
 static void genRRC (iCode *ic)
 {
   operand *left , *result ;
-  int size, offset = 0, same;
+  int size, same;
 
   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
@@ -6395,20 +6421,16 @@ static void genRRC (iCode *ic)
   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
 
   /* get the lsb and put it into the carry */
-  pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
-
-  offset = 0 ;
+  pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
 
   while(size--) {
 
     if(same) {
-      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
+      pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),size));
     } else {
-      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
-      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size));
+      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
     }
-
-    offset++;
   }
 
   pic16_freeAsmop(left,NULL,ic,TRUE);
@@ -6610,9 +6632,9 @@ static void AccRsh (int shCount, int andmask)
                 case 7 :
                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
                         break;
-               default:
-                       // Rotating by 8 is a NOP.
-                       break;
+                default:
+                        // Rotating by 8 is a NOP.
+                        break;
         }
 
         if (andmask)
@@ -7004,19 +7026,18 @@ static void shiftL2Left2Result (operand *left, int offl,
       }
       break;
     case 6:
-      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
-      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
-      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
+      pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl));
       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
-
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
-      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
-      pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
-      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
-      pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
-      pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
-      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRNCF,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl+MSB16));
+      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_RRNCF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xc0));
+      pic16_emitpcode(POC_ANDWF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_ANDFW,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_XORFW,  pic16_popGet(AOP(result),offr));
+      pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(result),offr+MSB16));
+      pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offr));
       break;
     case 7:
       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
@@ -7265,7 +7286,7 @@ static void shiftLLong (operand *left, operand *result, int offr )
                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
                 }
         } else {
-                pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
+                pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB));
         }
 
     if (size > LSB+offr ){
@@ -7668,7 +7689,7 @@ static void genRightShiftLiteral (operand *left,
     } // for
   } else if (shCount >= (lsize * 8)) {
     if (sign) {
-      /* 
+      /*
        * Do NOT use
        *    CLRF    result
        *    BTFSC   left, 7