fixed check_syntax(), "break xram r 0x7654" did not work.
[fw/sdcc] / src / pic / genarith.c
index 1741ad978be83da47c3551c1e7df64ca41ed8027..241ca2f3171b244374aec5ded7dd7d65ec5b15e4 100644 (file)
@@ -36,7 +36,7 @@
 #include "SDCCglobl.h"
 #include "newalloc.h"
 
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
 #define __FUNCTION__           __FILE__
 #endif
 
@@ -113,6 +113,60 @@ const char *AopType(short type)
 
   return "BAD TYPE";
 }
+
+const char *pCodeOpType(  pCodeOp *pcop)
+{
+
+  if(pcop) {
+
+    switch(pcop->type) {
+
+    case  PO_NONE:
+      return "PO_NONE";
+    case  PO_W:
+      return  "PO_W";
+    case  PO_STATUS:
+      return  "PO_STATUS";
+    case  PO_FSR:
+      return  "PO_FSR";
+    case  PO_INDF:
+      return  "PO_INDF";
+    case  PO_INTCON:
+      return  "PO_INTCON";
+    case  PO_GPR_REGISTER:
+      return  "PO_GPR_REGISTER";
+    case  PO_GPR_BIT:
+      return  "PO_GPR_BIT";
+    case  PO_GPR_TEMP:
+      return  "PO_GPR_TEMP";
+    case  PO_SFR_REGISTER:
+      return  "PO_SFR_REGISTER";
+    case  PO_PCL:
+      return  "PO_PCL";
+    case  PO_PCLATH:
+      return  "PO_PCLATH";
+    case  PO_LITERAL:
+      return  "PO_LITERAL";
+    case  PO_IMMEDIATE:
+      return  "PO_IMMEDIATE";
+    case  PO_DIR:
+      return  "PO_DIR";
+    case  PO_CRY:
+      return  "PO_CRY";
+    case  PO_BIT:
+      return  "PO_BIT";
+    case  PO_STR:
+      return  "PO_STR";
+    case  PO_LABEL:
+      return  "PO_LABEL";
+    case  PO_WILD:
+      return  "PO_WILD";
+    }
+  }
+
+  return "BAD PO_TYPE";
+}
+
 /*-----------------------------------------------------------------*/
 /* genPlusIncr :- does addition with increment if possible         */
 /*-----------------------------------------------------------------*/
@@ -684,34 +738,50 @@ static void genAddLit (iCode *ic, int lit)
       }
 
     } else {
+      int clear_carry=0;
 
       /* left is not the accumulator */
       if(lit & 0xff) {
        emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
        emitpcode(POC_ADDFW, popGet(AOP(left),0));
-      } else
+      } else {
        emitpcode(POC_MOVFW, popGet(AOP(left),0));
-
+       /* We don't know the state of the carry bit at this point */
+       clear_carry = 1;
+      }
       //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
       emitMOVWF(result,0);
-      lit >>= 8;
       while(--size) {
       
+       lit >>= 8;
        if(lit & 0xff) {
-         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
-         //emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
-         emitMOVWF(result,offset);
-         emitpcode(POC_MOVFW, popGet(AOP(left),offset));
-         emitSKPNC;
-         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
-         emitpcode(POC_ADDWF,  popGet(AOP(result),offset));
+         if(clear_carry) {
+           /* The ls byte of the lit must've been zero - that 
+              means we don't have to deal with carry */
+
+           emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
+           emitpcode(POC_ADDFW,  popGet(AOP(left),offset));
+           emitpcode(POC_MOVWF, popGet(AOP(left),offset));
+
+           clear_carry = 0;
+
+         } else {
+           emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
+           //emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
+           emitMOVWF(result,offset);
+           emitpcode(POC_MOVFW, popGet(AOP(left),offset));
+           emitSKPNC;
+           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
+           emitpcode(POC_ADDWF,  popGet(AOP(result),offset));
+         }
+
        } else {
          emitpcode(POC_CLRF,  popGet(AOP(result),offset));
          emitpcode(POC_RLF,   popGet(AOP(result),offset));
          emitpcode(POC_MOVFW, popGet(AOP(left),offset));
          emitpcode(POC_ADDWF, popGet(AOP(result),offset));
        }
-      offset++;
+       offset++;
       }
     }
   }
@@ -905,14 +975,15 @@ void genPlus (iCode *ic)
        if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
          emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0));
        else {
-         if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
-             (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
-           emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0));
-         } else {
-           emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0));
-           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
-             emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
-         }
+         PIC_OPCODE poc = POC_ADDFW;
+
+         if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
+             (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
+             (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE)))
+           poc = POC_ADDLW;
+         emitpcode(poc, popGet(AOP(IC_LEFT(ic)),0));
+         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
+           emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
        }
       }
     }
@@ -1104,22 +1175,33 @@ bool genMinusDec (iCode *ic)
 }
 
 /*-----------------------------------------------------------------*/
-/* addSign - complete with sign                                    */
+/* addSign - propogate sign bit to higher bytes                    */
 /*-----------------------------------------------------------------*/
 void addSign(operand *result, int offset, int sign)
 {
-    int size = (pic14_getDataSize(result) - offset);
-    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-    if(size > 0){
-        if(sign){
-            pic14_emitcode("rlc","a");
-            pic14_emitcode("subb","a,acc");
-            while(size--)
-                aopPut(AOP(result),"a",offset++); 
-        } else
-            while(size--)
-                aopPut(AOP(result),"#0",offset++);
-    }
+  int size = (pic14_getDataSize(result) - offset);
+  DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+  if(size > 0){
+    if(sign && offset) {
+
+      if(size == 1) {
+       emitpcode(POC_CLRF,popGet(AOP(result),offset));
+       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
+       emitpcode(POC_DECF, popGet(AOP(result),offset));
+      } else {
+
+       emitpcode(POC_MOVLW, popGetLit(0));
+       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
+       emitpcode(POC_MOVLW, popGetLit(0xff));
+       while(size--)
+         emitpcode(POC_MOVWF, popGet(AOP(result),size));
+
+      }
+    } else
+      while(size--)
+       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1490,6 +1572,8 @@ void genUMult8XLit_16 (operand *left,
 
   unsigned int lit;
   unsigned int i,have_first_bit;
+  int same;
+  pCodeOp *temp;
 
   if (AOP_TYPE(right) != AOP_LIT){
     fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
@@ -1505,11 +1589,165 @@ void genUMult8XLit_16 (operand *left,
   lit &= 0xff;
   pic14_emitcode(";","Unrolled 8 X 8 multiplication");
 
+  same = pic14_sameRegs(AOP(left), AOP(result));
+
+  if(same) {
+    switch(lit) {
+    case 0:
+      emitpcode(POC_CLRF,  popGet(AOP(left),0));
+      return;
+    case 2:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 3:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 4:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 5:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 5*F
+      return;
+    case 6:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 7:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 5*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 7*F
+      return;
+    case 8:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 8*F
+      return;
+    case 9:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 10:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 5*F
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 11:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 8*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 11*F
+      return;
+    case 12:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));
+      return;
+    case 13:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 8*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 13*F
+      return;
+    case 14:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 8*F
+      emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 11*F
+      emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 14*F
+      return;
+    case 15:
+      temp = popGetTempReg();
+      if(!temp) {
+       fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__);
+       exit(1);
+      }
+      emitpcode(POC_SWAPFW, popGet(AOP(left),0));
+      emitpcode(POC_MOVWF,  temp);
+      emitpcode(POC_ANDLW,  popGetLit(0xf0));
+      emitpcode(POC_MOVWF,  popGet(AOP(left),0));
+      emitpcode(POC_SWAPFW, temp);
+      emitpcode(POC_SUBWF,  popGet(AOP(left),0));
+      popReleaseTempReg(temp);
+      return;
+    case 16:
+      emitpcode(POC_SWAPFW, popGet(AOP(left),0));
+      emitpcode(POC_ANDLW,  popGetLit(0xf0));
+      emitpcode(POC_MOVWF,  popGet(AOP(left),0));
+      return;
+    case 17:
+      emitpcode(POC_SWAPFW, popGet(AOP(left),0));
+      emitpcode(POC_ANDLW,  popGetLit(0xf0));
+      emitpcode(POC_ADDWF,  popGet(AOP(left),0));
+      return;
+    case 32:
+      emitpcode(POC_SWAPF,  popGet(AOP(left),0));
+      emitpcode(POC_RLFW,   popGet(AOP(left),0));
+      emitpcode(POC_ANDLW,  popGetLit(0xe0));
+      emitpcode(POC_MOVWF,  popGet(AOP(left),0));
+      return;
+    case 64:
+      emitpcode(POC_SWAPF,  popGet(AOP(left),0));
+      emitpcode(POC_RLF,    popGet(AOP(left),0));
+      emitpcode(POC_RLFW,   popGet(AOP(left),0));
+      emitpcode(POC_ANDLW,  popGetLit(0xc0));
+      emitpcode(POC_MOVWF,  popGet(AOP(left),0));
+      return;
+    case 128:
+      emitpcode(POC_RRFW,   popGet(AOP(left),0));
+      emitpcode(POC_CLRF,   popGet(AOP(left),0));
+      emitpcode(POC_RRF,    popGet(AOP(left),0));
+      return;
+
+    }
+  } else {
+
+    switch(lit) {
+    case 0:
+      emitpcode(POC_CLRF,  popGet(AOP(result),0));
+      emitpcode(POC_CLRF,  popCopyReg(result_hi));
+      return;
+    case 2:
+      emitpcode(POC_MOVFW, popGet(AOP(left),0));
+      emitpcode(POC_MOVWF, popGet(AOP(result),0));
+      emitpcode(POC_ADDWF, popGet(AOP(result),0));
+      emitpcode(POC_CLRF,  popCopyReg(result_hi));
+      emitpcode(POC_RLF,   popCopyReg(result_hi));
+      return;
+    }
 
-  if(!lit) {
-    emitpcode(POC_CLRF,  popGet(AOP(result),0));
-    emitpcode(POC_CLRF,  popCopyReg(result_hi));
-    return;
   }
 
   emitpcode(POC_MOVFW, popGet(AOP(left),0));
@@ -1553,6 +1791,11 @@ void genUMult8X8_16 (operand *left,
     result_hi = PCOR(popGet(AOP(result),1));
   }
 
+  if (AOP_TYPE(right) == AOP_LIT) {
+    genUMult8XLit_16(left,right,result,result_hi);
+    return;
+  }
+
   if(!looped) {
     pic14_emitcode(";","Unrolled 8 X 8 multiplication");
 
@@ -1591,16 +1834,19 @@ void genUMult8X8_16 (operand *left,
 
   } else {
     symbol  *tlbl = newiTempLabel(NULL);
-    pCodeOp *temp = popGetTempReg();
+    pCodeOp *temp;
 
 
     pic14_emitcode(";","Looped 8 X 8 multiplication");
 
     emitpcode(POC_CLRF,  popGet(AOP(result),0));
     emitpcode(POC_CLRF,  popCopyReg(result_hi));
+
     emitpcode(POC_BSF,   newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),7,0));
 
     emitpcode(POC_MOVFW, popGet(AOP(right),0));
+
+    temp = popGetTempReg();
     emitpcode(POC_MOVWF, popCopyReg(PCOR(temp)));
 
     emitpcode(POC_MOVFW, popGet(AOP(left),0));