* src/pic16/{gen.c,genarith.c}: replaced sign-extension
[fw/sdcc] / src / pic16 / genarith.c
index 39f3dcbdb21d765781cf159bb9cc4f1b9c50e027..fe7788522b861e40d097deacf5af8aee7d2a68da 100644 (file)
@@ -416,6 +416,7 @@ static void adjustArithmeticResult(iCode *ic)
 }
 #endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genAddlit - generates code for addition                         */
 /*-----------------------------------------------------------------*/
@@ -438,6 +439,7 @@ static void genAddLit2byte (operand *result, int offr, int lit)
   }
 
 }
+#endif
 
 static void emitMOVWF(operand *reg, int offset)
 {
@@ -456,19 +458,90 @@ static void emitMOVWF(operand *reg, int offset)
 static void genAddLit (iCode *ic, int lit)
 {
 
-  int size,same;
-  int lo;
+  int size,sizeL,same;
+  int i, llit;
 
   operand *result;
   operand *left;
+  sym_link *lleft;
 
     FENTRY;
 
 
   left = IC_LEFT(ic);
+  lleft = operandType (left);
   result = IC_RESULT(ic);
   same = pic16_sameRegs(AOP(left), AOP(result));
   size = pic16_getDataSize(result);
+  sizeL = pic16_getDataSize(left);
+  llit = lit;
+
+#define MIN(a,b)       (((a) < (b)) ? (a) : (b))
+  /* move left to result -- possibly sign extend */
+  for (i=0; i < MIN(size, sizeL); i++) {
+    pic16_mov2f (AOP(result), AOP(left), i);
+  } // for i
+#undef MIN
+
+  /* extend to result size */
+  if (IS_UNSIGNED(lleft)) {
+    /* zero-extend */
+    for (i = sizeL; i < size; i++) {
+      pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
+    } // for i
+  } else {
+    /* sign-extend */
+    if (size == sizeL + 1) {
+      pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), sizeL));
+      pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7));
+      pic16_emitpcode (POC_SETF, pic16_popGet (AOP(result), sizeL));
+    } else {
+      pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
+      pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7));
+      pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
+      
+      for (i=sizeL; i < size; i++) {
+        pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), i));
+      } // for i
+    } // if
+  } // if (SIGNED)
+
+  /* special cases */
+  if (lit == 0) {
+    /* nothing to do */
+  } else if (lit == 1) {
+    switch (size) {
+    case 1:
+      /* handled below */
+      break;
+    case 2:
+      pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(result), 0));
+      break;
+    default:
+      assert (size > 2);
+      pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), 0));
+      for (i=1; i < size-1; i++) {
+        emitSKPNC; /* a jump here saves up to 2(size-2)cycles */
+        pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), i));
+      } // for i
+      emitSKPNC;
+      break;
+    } // switch
+    
+    pic16_emitpcode (POC_INCF, pic16_popGet (AOP(result), size-1));
+  } else {
+    /* general case */
+
+    /* add literal to result */
+    for (i=0; i < size; i++) {
+      pic16_emitpcode (POC_MOVLW, pic16_popGetLit (llit));
+      llit >>= 8; /* FIXME: arithmetic right shift for signed literals? */
+      pic16_emitpcode (i == 0 ? POC_ADDWF : POC_ADDWFC,
+       pic16_popGet (AOP(result), i));
+    }
+  }
+
+#if 0
 
   if(same) {
 
@@ -739,6 +812,7 @@ static void genAddLit (iCode *ic, int lit)
       }
     }
   }
+#endif
 }
 
 /*-----------------------------------------------------------------*/
@@ -985,7 +1059,7 @@ void pic16_genPlus (iCode *ic)
                                for(i=size; i< AOP_SIZE(result); i++) {
                                        pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
                                        pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                                       pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i));
+                                       pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),i));
                                        pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
                                        pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
                                }
@@ -1020,20 +1094,16 @@ void pic16_genPlus (iCode *ic)
                        // add leftover bytes
                        // either left or right is too short
                        for (i=size; i < AOP_SIZE(result); i++) {
-                         fprintf (stderr, "%s:%d: new code...\n", __FUNCTION__, __LINE__);
-                         pic16_emitcode ("; ", "new arithmetics... test me...");
                          // get right operand into WREG
                          if (i < AOP_SIZE(right)) {
                            pic16_mov2w (AOP(right), i);
                          } else {
-                           pic16_emitcode ("; =##", "right too short");
                            // right is too short
                            pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
                            if (!SPEC_USIGN(getSpec(operandType(right)))) {
-                             pic16_emitcode ("; =##", "right signed");
                              // right operand is signed
                              pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),AOP_SIZE(right)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                             pic16_emitpcode(POC_COMF, pic16_popCopyReg (&pic16_pc_wreg));
+                             pic16_emitpcode(POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
                            }
                          }
 
@@ -1046,111 +1116,24 @@ void pic16_genPlus (iCode *ic)
                              pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
                            }
                          } else {
-                           pic16_emitcode ("; =##", "left too short");
                            // left is too short
                            pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
                            if (!SPEC_USIGN(getSpec(operandType(left)))) {
-                             pic16_emitcode ("; =##", "left signed");
                              // left operand is signed
                              pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                             pic16_emitpcode(POC_COMF, pic16_popGet (AOP(result), i));
+                             pic16_emitpcode(POC_SETF, pic16_popGet (AOP(result), i));
                            }
                            pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
                          }
                        } // for i
                        goto release;
-                       
-#if 0
-                       // add leftover bytes
-                       if (SPEC_USIGN(getSpec(operandType(right)))) {
-                               // right is unsigned
-                               for(i=size; i< AOP_SIZE(result); i++) {
-                                       if (pic16_sameRegs(AOP(left), AOP(result)))
-                                       {
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
-                                       } else { // not same
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
-                                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
-                                       }
-                               }
-                       } else {
-                               // right is signed
-                               for(i=size; i< AOP_SIZE(result); i++) {
-                                       if(size < AOP_SIZE(left)) {
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                                               pic16_emitpcode(POC_COMFW, pic16_popCopyReg(&pic16_pc_wreg));
-                                               if (pic16_sameRegs(AOP(left), AOP(result)))
-                                               {
-                                                       pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
-                                               } else { // not same
-                                                       pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
-                                                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
-                                               }
-                                       } else {
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), i));
-                                       }
-                               }
-                       }
-                       goto release;
-#endif
                }
 
        }
 
        assert( 0 );
-       // TODO:        anything from here to before "release:" is probably obsolete and should be removed
-       //              when the regression tests are stable
-
-       if (AOP_SIZE(result) > AOP_SIZE(right)) {
-               int sign =  !(SPEC_USIGN(getSpec(operandType(left))) |
-                               SPEC_USIGN(getSpec(operandType(right))) );
-
-
-               /* Need to extend result to higher bytes */
-               size = AOP_SIZE(result) - AOP_SIZE(right) - 1;
-
-               /* First grab the carry from the lower bytes */
-               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
-               pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offset));
-
-
-               if(sign) {
-                       /* Now this is really horrid. Gotta check the sign of the addends and propogate
-                       * to the result */
-
-                       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offset));
-                       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offset));
-
-                       /* if chars or ints or being signed extended to longs: */
-                       if(size) {
-                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
-                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
-                       }
-               }
-
-               offset++;
-               while(size--) {
-      
-                       if(sign)
-                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
-                       else
-                               pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
-
-                       offset++;
-               }
-       }
-
-
-       //adjustArithmeticResult(ic);
-
-       release:
+       
+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);
@@ -1271,7 +1254,7 @@ void pic16_addSign(operand *result, int offset, int sign)
       if(size == 1) {
        pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
        pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
+       pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
       } else {
 
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
@@ -1576,7 +1559,7 @@ void pic16_genMinus (iCode *ic)
        if (!SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
          // signed -- sign extend the right operand
          pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),AOP_SIZE(IC_RIGHT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-         pic16_emitpcode (POC_COMF, pic16_popCopyReg (&pic16_pc_wreg));
+         pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
        }
       }
       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
@@ -1591,7 +1574,7 @@ void pic16_genMinus (iCode *ic)
          if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
            // signed -- sign extend the left operand
            pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),AOP_SIZE(IC_LEFT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-           pic16_emitpcode (POC_COMF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); // keep CARRY/#BORROW bit intact!
+           pic16_emitpcode (POC_SETF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); // keep CARRY/#BORROW bit intact!
          }
          pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
        }