* src/pic16/gen.c (pic16_storeForReturn): fragile fix for
[fw/sdcc] / src / pic16 / genarith.c
index 9f6a859579a900255da5c32ce4df61ccb51700a4..7766ae7d1e5db660997f778d897cc9da481c987e 100644 (file)
 #include "pcode.h"
 #include "gen.h"
 
+#if 1
+#define pic16_emitcode DEBUGpic16_emitcode
+#endif
 
 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result);
-
+void pic16_emitpcomment(char *, ...);
+pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
 const char *pic16_AopType(short type)
 {
   switch(type) {
-  case AOP_LIT:
-    return "AOP_LIT";
-    break;
-  case AOP_REG:
-    return "AOP_REG";
-    break;
-  case AOP_DIR:
-    return "AOP_DIR";
-    break;
-  case AOP_DPTR:
-    return "AOP_DPTR";
-    break;
-  case AOP_DPTR2:
-    return "AOP_DPTR2";
-    break;
-  case AOP_R0:
-    return "AOP_R0";
-    break;
-  case AOP_R1:
-    return "AOP_R1";
-    break;
-  case AOP_STK:
-    return "AOP_STK";
-    break;
-  case AOP_IMMD:
-    return "AOP_IMMD";
-    break;
-  case AOP_STR:
-    return "AOP_STR";
-    break;
-  case AOP_CRY:
-    return "AOP_CRY";
-    break;
-  case AOP_ACC:
-    return "AOP_ACC";
-    break;
-  case AOP_PCODE:
-    return "AOP_PCODE";
-    break;
+  case AOP_LIT:                return "AOP_LIT";
+  case AOP_REG:        return "AOP_REG";
+  case AOP_DIR:        return "AOP_DIR";
+  case AOP_DPTR:       return "AOP_DPTR";
+  case AOP_DPTR2:      return "AOP_DPTR2";
+  case AOP_FSR0:       return "AOP_FSR0";
+  case AOP_FSR2:       return "AOP_FSR2";
+  case AOP_R0:         return "AOP_R0";
+  case AOP_R1:         return "AOP_R1";
+  case AOP_STK:                return "AOP_STK";
+  case AOP_IMMD:       return "AOP_IMMD";
+  case AOP_STR:                return "AOP_STR";
+  case AOP_CRY:                return "AOP_CRY";
+  case AOP_ACC:                return "AOP_ACC";
+  case AOP_PCODE:      return "AOP_PCODE";
+  case AOP_STA:                return "AOP_STA";
   }
 
   return "BAD TYPE";
 }
 
-const char *pic16_pCodeOpType(  pCodeOp *pcop)
+const char *pic16_pCodeOpType(pCodeOp *pcop)
 {
 
   if(pcop) {
 
     switch(pcop->type) {
 
-    case  PO_NONE:
-      return "PO_NONE";
-    case  PO_W:
-      return  "PO_W";
-    case  PO_WREG:
-      return  "PO_WREG";
-    case  PO_STATUS:
-      return  "PO_STATUS";
-    case  PO_BSR:
-      return  "PO_BSR";
-    case  PO_FSR0:
-      return  "PO_FSR0";
-    case  PO_INDF0:
-      return  "PO_INDF0";
-    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_REL_ADDR:
-      return "PO_REL_ADDR";
-    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";
+    case PO_NONE:              return "PO_NONE";
+    case PO_W:                 return  "PO_W";
+    case PO_WREG:              return  "PO_WREG";
+    case PO_STATUS:            return  "PO_STATUS";
+    case PO_BSR:               return  "PO_BSR";
+    case PO_FSR0:              return  "PO_FSR0";
+    case PO_INDF0:             return  "PO_INDF0";
+    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_PCLATU:            return  "PO_PCLATU";
+    case PO_PRODL:             return  "PO_PRODL";
+    case PO_PRODH:             return  "PO_PRODH";
+    case PO_LITERAL:           return  "PO_LITERAL";
+    case PO_REL_ADDR:          return "PO_REL_ADDR";
+    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";
+}
+
+const char *pic16_pCodeOpSubType(pCodeOp *pcop)
+{
+
+  if(pcop && (pcop->type == PO_GPR_BIT)) {
+
+    switch(PCORB(pcop)->subtype) {
+
+    case PO_NONE:              return "PO_NONE";
+    case PO_W:                 return  "PO_W";
+    case PO_WREG:              return  "PO_WREG";
+    case PO_STATUS:            return  "PO_STATUS";
+    case PO_BSR:               return  "PO_BSR";
+    case PO_FSR0:              return  "PO_FSR0";
+    case PO_INDF0:             return  "PO_INDF0";
+    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_PCLATU:            return  "PO_PCLATU";
+    case PO_PRODL:             return  "PO_PRODL";
+    case PO_PRODH:             return  "PO_PRODH";
+    case PO_LITERAL:           return  "PO_LITERAL";
+    case PO_REL_ADDR:          return "PO_REL_ADDR";
+    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";
     }
   }
 
@@ -163,10 +163,11 @@ const char *pic16_pCodeOpType(  pCodeOp *pcop)
 /*-----------------------------------------------------------------*/
 bool pic16_genPlusIncr (iCode *ic)
 {
-    unsigned int icount ;
-    unsigned int size = pic16_getDataSize(IC_RESULT(ic));
+  unsigned int icount ;
+  unsigned int size = pic16_getDataSize(IC_RESULT(ic));
+
+    FENTRY;
 
-    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
     DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
                         pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
                         pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
@@ -180,8 +181,8 @@ bool pic16_genPlusIncr (iCode *ic)
     
     DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
     /* if the literal value of the right hand side
-       is greater than 1 then it is faster to add */
-    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 1)          // this was > 2 why? VR
+       is greater than 2 then it is faster to add */
+    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
         return FALSE ;
     
     /* if increment 16 bits in register */
@@ -194,7 +195,7 @@ bool pic16_genPlusIncr (iCode *ic)
       //pic16_emitcode("incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
 
       while(--size) {
-       emitSKPNZ;
+       emitSKPNC;
        pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),offset++));
        //pic16_emitcode(" incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
       }
@@ -202,9 +203,9 @@ bool pic16_genPlusIncr (iCode *ic)
       return TRUE;
     }
     
-    DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
+//    DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
     /* if left is in accumulator  - probably a bit operation*/                         // VR - why this is a bit operation?!
-    if( strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
+    if( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) &&
        (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
       
       pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
@@ -228,7 +229,6 @@ bool pic16_genPlusIncr (iCode *ic)
     }
 
 
-
     /* if the sizes are greater than 1 then we cannot */
     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
         AOP_SIZE(IC_LEFT(ic)) > 1   )
@@ -259,6 +259,8 @@ void pic16_outBitAcc(operand *result)
     /* if the result is a bit */
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
+    assert(0); // not implemented for PIC16?
+
     if (AOP_TYPE(result) == AOP_CRY){
         pic16_aopPut(AOP(result),"a",0);
     }
@@ -275,8 +277,7 @@ void pic16_outBitAcc(operand *result)
 /*-----------------------------------------------------------------*/
 void pic16_genPlusBits (iCode *ic)
 {
-
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  FENTRY;
 
   DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
                       pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
@@ -415,12 +416,14 @@ static void adjustArithmeticResult(iCode *ic)
 }
 #endif
 
+#if 1
 /*-----------------------------------------------------------------*/
 /* genAddlit - generates code for addition                         */
 /*-----------------------------------------------------------------*/
 static void genAddLit2byte (operand *result, int offr, int lit)
 {
-
+  FENTRY;
+  
   switch(lit & 0xff) {
   case 0:
     break;
@@ -436,6 +439,7 @@ static void genAddLit2byte (operand *result, int offr, int lit)
   }
 
 }
+#endif
 
 static void emitMOVWF(operand *reg, int offset)
 {
@@ -451,6 +455,9 @@ static void emitMOVWF(operand *reg, int offset)
 
 }
 
+
+#if 1
+
 static void genAddLit (iCode *ic, int lit)
 {
 
@@ -460,7 +467,7 @@ static void genAddLit (iCode *ic, int lit)
   operand *result;
   operand *left;
 
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    FENTRY;
 
 
   left = IC_LEFT(ic);
@@ -525,6 +532,13 @@ static void genAddLit (iCode *ic, int lit)
          pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
          pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
          pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       default: /* 0x01LL */
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
+         emitSKPNC;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
        }         
        break;
 
@@ -564,10 +578,9 @@ static void genAddLit (iCode *ic, int lit)
          genAddLit2byte (result, MSB16, hi);
          break;
        case 1:  /* 0xHH01 */
-         pic16_emitpcode(POC_MOVLW,pic16_popGetLit((hi+1)&0xff));
-         pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
          pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
-         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
          break;
 /*     case 0xff: * 0xHHff *
          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
@@ -579,9 +592,7 @@ static void genAddLit (iCode *ic, int lit)
          pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
          pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
          pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
-         emitSKPNC;
-         pic16_emitpcode(POC_MOVLW,pic16_popGetLit((hi+1) & 0xff));
-         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
          break;
        }
 
@@ -596,44 +607,8 @@ static void genAddLit (iCode *ic, int lit)
        lo = BYTEofLONG(lit,0);
 
        if(carry_info) {
-         switch(lo) {
-         case 0:
-           switch(carry_info) {
-           case 1:
-             emitSKPNZ;
-             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
-             break;
-           case 2:
-             pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
-             pic16_emitpcode(POC_ANDLW, pic16_popGetLit(1));
-             pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
-             break;
-           default: /* carry_info = 3  */
-             emitSKPNC;
-             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
-             carry_info = 1;
-             break;
-           }
-           break;
-         case 0xff:
-           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
-           if(carry_info==1) 
-             emitSKPZ;
-           else
-             emitSKPC;
-           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
-           break;
-         default:
-           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
-           if(carry_info==1) 
-             emitSKPNZ;
-           else
-             emitSKPNC;
-           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo+1));
-           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
-           carry_info=2;
-           break;
-         }
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
        }else {
          /* no carry info from previous step */
          /* this means this is the first time to add */
@@ -679,7 +654,6 @@ static void genAddLit (iCode *ic, int lit)
 
        } 
       } 
-    }
 
 */
     }
@@ -705,10 +679,8 @@ static void genAddLit (iCode *ic, int lit)
        /* left addend is in a register */
        switch(lit & 0xff) {
        case 0:
-         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+         pic16_mov2w(AOP(left),0);
          emitMOVWF(result, 0);
-         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
-         emitMOVWF(result,0);
          break;
        case 1:
          pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
@@ -736,341 +708,721 @@ static void genAddLit (iCode *ic, int lit)
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
       } else {
-       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
+       pic16_mov2w(AOP(left),0);
        /* We don't know the state of the carry bit at this point */
        clear_carry = 1;
       }
       //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
       emitMOVWF(result,0);
       while(--size) {
-      
        lit >>= 8;
-       if(lit & 0xff) {
-         if(clear_carry) {
-           /* The ls byte of the lit must've been zero - that 
-              means we don't have to deal with carry */
-
-           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
-           pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(left),offset));
-           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),offset));
-
-           clear_carry = 0;
-
-         } else {
-           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
-           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset,FALSE,FALSE));
-           emitMOVWF(result,offset);
-           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
-           emitSKPNC;
-           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
-           pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),offset));
-         }
-
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+       if (offset < AOP_SIZE(left)) {
+         pic16_emitpcode(clear_carry ? POC_ADDFW : POC_ADDFWC, pic16_popGet(AOP(left),offset));
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
        } else {
-         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
-         pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offset));
-         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
-         pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
+         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+         if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
+           /* sign-extend left (in result) */
+            pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left),AOP_SIZE(left)-1,7));
+           pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
+         }
+         pic16_emitpcode(clear_carry ? POC_ADDWF : POC_ADDWFC, pic16_popGet(AOP(result),offset));
        }
+       clear_carry = 0;
        offset++;
       }
     }
   }
 }
 
-/*-----------------------------------------------------------------*/
-/* pic16_genPlus - generates code for addition                     */
-/*-----------------------------------------------------------------*/
-void pic16_genPlus (iCode *ic)
-{
-  int size, offset = 0;
-  operand *result, *left, *right;
-  
-  /* special cases :- */
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
-
-#if 1
-       result = IC_RESULT(ic);
-       left = IC_LEFT(ic);
-       right = IC_RIGHT(ic);
-  pic16_aopOp (left,ic,FALSE);
-  pic16_aopOp (right,ic,FALSE);
-  pic16_aopOp (result,ic,TRUE);
-  DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
-
 #else
-  pic16_aopOp (IC_LEFT(ic),ic,FALSE);
-  pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
-  pic16_aopOp (IC_RESULT(ic),ic,TRUE);
-  DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
-#endif
+    /* this fails when result is an SFR because value is written there
+     * during addition and not at the end */
+     
+static void genAddLit (iCode *ic, int lit)
+{
 
+  int size,sizeL,same;
+  int i, llit;
 
-  /* if literal, literal on the right or
-     if left requires ACC or right is already
-     in ACC */
+  operand *result;
+  operand *left;
+  sym_link *lleft;
 
-  if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
-    operand *t = IC_RIGHT(ic);
-    IC_RIGHT(ic) = IC_LEFT(ic);
-    IC_LEFT(ic) = t;
-  }
+    FENTRY;
 
-  /* if both left & right are in bit space */
-  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-      AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-    pic16_genPlusBits (ic);
-    goto release ;
-  }
 
-  /* if left in bit space & right literal */
-  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-      AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
-    /* if result in bit space */
-    if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
-      if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
-       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_RESULT(ic)),0));
-       if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
-         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
-      }
+  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 {
-      size = pic16_getDataSize(IC_RESULT(ic));
-      while (size--) {
-       MOVA(pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
-       pic16_emitcode("addc","a,#00  ;%d",__LINE__);
-       pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
-      }
+      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));
     }
-    goto release ;
   }
 
-  /* if I can do an increment instead
-     of add then GOOD for ME */
-  if (pic16_genPlusIncr (ic) == TRUE)
-    goto release;   
-
-  size = pic16_getDataSize(IC_RESULT(ic));
-
-  if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
-    /* Add a literal to something else */
-    //bool know_W=0;
-    unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-    //      unsigned l1=0;
-
-    //      offset = 0;
-    DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
+#if 0
 
-    genAddLit (ic,  lit);
-    goto release;
+  if(same) {
 
-  } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+    /* Handle special cases first */
+    if(size == 1) 
+      genAddLit2byte (result, 0, lit);
+     
+    else if(size == 2) {
+      int hi = 0xff & (lit >> 8);
+      lo = lit & 0xff;
 
-    pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
-    pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-    pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      switch(hi) {
+      case 0: 
 
-    /* here we are adding a bit to a char or int */
-    if(size == 1) {
-      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+       /* lit = 0x00LL */
+       DEBUGpic16_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
+       switch(lo) {
+       case 0:
+         break;
+       case 1:
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 0xff:
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
 
-       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+         break;
+       default:
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
+         emitSKPNC;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
 
-       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
-       pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-      } else {
 
-       if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
-         pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
+       }
+       break;
 
-         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
-         pic16_emitcode(" xorlw","1");
-       } else {
-         pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
-         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
-         pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+      case 1:
+       /* lit = 0x01LL */
+       DEBUGpic16_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
+       switch(lo) {
+       case 0:  /* 0x0100 */
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 1:  /* 0x0101  */
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 0xff: /* 0x01ff */
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         break;
+       default: /* 0x01LL */
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
+         emitSKPNC;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
+       }         
+       break;
 
-         pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
-         pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-       }
+      case 0xff:
+       DEBUGpic16_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
+       /* lit = 0xffLL */
+       switch(lo) {
+       case 0:  /* 0xff00 */
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
+         break;
+       case 1:  /*0xff01 */
+         pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
+         break;
+/*     case 0xff: * 0xffff *
+         pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         break;
+*/
+       default:
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
+         emitSKPC;
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
          
-       if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
-           
-         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
-           pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
-           pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
-           emitSKPZ;
-           pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
-         } else {
-           pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
-           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-         }
        }
-      }
-
-    } else {
-      int offset = 1;
-      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       emitCLRZ;
-       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
 
-       pic16_emitcode("clrz","");
+       break;
+       
+      default:
+       DEBUGpic16_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
 
-       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
-       pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-
-      } else {
+       /* lit = 0xHHLL */
+       switch(lo) {
+       case 0:  /* 0xHH00 */
+         genAddLit2byte (result, MSB16, hi);
+         break;
+       case 1:  /* 0xHH01 */
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
+         pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
+         break;
+/*     case 0xff: * 0xHHff *
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
+         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
+         break;
+*/     default:  /* 0xHHLL */
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
+         pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
+         break;
+       }
 
-       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
-       emitMOVWF(IC_RIGHT(ic),0);
+      }
+    } else {
+      int carry_info = 0;
+      int offset = 0;
+      /* size > 2 */
+      DEBUGpic16_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
 
-       pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
-       pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-       pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      while(size--) {
+       lo = BYTEofLONG(lit,0);
 
+       if(carry_info) {
+         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
+       }else {
+         /* no carry info from previous step */
+         /* this means this is the first time to add */
+         switch(lo) {
+         case 0:
+           break;
+         case 1:
+           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
+           carry_info=1;
+           break;
+         default:
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
+           if(lit <0x100) 
+             carry_info = 3;  /* Were adding only one byte and propogating the carry */
+           else
+             carry_info = 2;
+           break;
+         }
+       }
+       offset++;
+       lit >>= 8;
       }
+    
+/*
+      lo = BYTEofLONG(lit,0);
 
-      while(--size){
-       emitSKPZ;
-       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset++));
-       //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
-      }
+      if(lit < 0x100) {
+       if(lo) {
+         if(lo == 1) {
+           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+           emitSKPNZ;
+         } else {
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
+           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+           emitSKPNC;
+         }
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE));
+         emitSKPNZ;
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE));
+
+       } 
+      } 
 
+*/
     }
-      
   } else {
-    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
-
-    /* Add the first bytes */
+    int offset = 1;
+    DEBUGpic16_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
 
-    if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-    } else {
+    if(size == 1) {
 
-      if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
-         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      if(AOP_TYPE(left) == AOP_ACC) {
+       /* left addend is already in accumulator */
+       switch(lit & 0xff) {
+       case 0:
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+         break;
+       default:
+         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+       }
       } else {
-
-       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0));
-
-       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
-         pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       else {
-         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;
-         pic16_emitpcode(poc, pic16_popGet(AOP(IC_LEFT(ic)),0));
-         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
-           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+       /* left addend is in a register */
+       switch(lit & 0xff) {
+       case 0:
+         pic16_mov2w(AOP(left),0);
+         emitMOVWF(result, 0);
+         break;
+       case 1:
+         pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+         break;
+       case 0xff:
+         pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
+         break;
+       default:
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
+         //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+         emitMOVWF(result,0);
        }
       }
-    }
-
-    size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
-    offset = 1;
 
+    } else {
+      int clear_carry=0;
 
-    while(size--){
-      if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
-       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-       pic16_emitcode("movf","%s,w",  pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
-       pic16_emitcode("movwf","%s",  pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
+      /* left is not the accumulator */
+      if(lit & 0xff) {
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
+      } else {
+       pic16_mov2w(AOP(left),0);
+       /* We don't know the state of the carry bit at this point */
+       clear_carry = 1;
       }
+      //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
+      emitMOVWF(result,0);
+      while(--size) {
+      
+       lit >>= 8;
+       if(lit & 0xff) {
+         if(clear_carry) {
+           /* The ls byte of the lit must've been zero - that 
+              means we don't have to deal with carry */
 
-      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-      emitSKPNC;
-      pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-      pic16_emitpcode(POC_ADDWF,   pic16_popGet(AOP(IC_RESULT(ic)),offset));
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+           pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(left),offset));
+           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
 
-      /*
-       pic16_emitcode("movf","%s,w",  pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-       emitSKPNC;
-       pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-       pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
-      */
+           clear_carry = 0;
 
-      offset++;
-    }
+         } else {
+           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+           pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),offset));
+           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+         }
 
+       } else {
+         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
+         pic16_mov2w(AOP(left),offset);
+         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
+       }
+       offset++;
+      }
+    }
   }
+#endif
+}
 
-  if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
-    int sign =  !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
-                 SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
-
-
-    /* Need to extend result to higher bytes */
-    size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
-
-    /* First grab the carry from the lower bytes */
-    pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-    pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
+#endif
 
-    if(sign) {
-      /* Now this is really horrid. Gotta check the sign of the addends and propogate
-       * to the result */
+/*-----------------------------------------------------------------*/
+/* pic16_genPlus - generates code for addition                     */
+/*-----------------------------------------------------------------*/
+void pic16_genPlus (iCode *ic)
+{
+  int i, size, offset = 0;
+  operand *result, *left, *right;
 
-      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
-      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
-      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+    FENTRY;
+    
+    /* special cases :- */
+       result = IC_RESULT(ic);
+       left = IC_LEFT(ic);
+       right = IC_RIGHT(ic);
+       pic16_aopOp (left,ic,FALSE);
+       pic16_aopOp (right,ic,FALSE);
+       pic16_aopOp (result,ic,TRUE);
+       DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
+       // pic16_DumpOp("(left)",left);
+
+       /* if literal, literal on the right or
+       if left requires ACC or right is already
+       in ACC */
+
+       if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) {
+               operand *t = right;
+               right = IC_RIGHT(ic) = left;
+               left = IC_LEFT(ic) = t;
+       }
 
-      /* 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(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
-       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
-      }
-    }
+       /* if both left & right are in bit space */
+       if (AOP_TYPE(left) == AOP_CRY &&
+               AOP_TYPE(right) == AOP_CRY) {
+               pic16_genPlusBits (ic);
+               goto release ;
+       }
 
-    offset++;
-    while(size--) {
+       /* if left in bit space & right literal */
+       if (AOP_TYPE(left) == AOP_CRY &&
+               AOP_TYPE(right) == AOP_LIT) {
+               /* if result in bit space */
+               if(AOP_TYPE(result) == AOP_CRY){
+                       if((unsigned long)floatFromVal(AOP(right)->aopu.aop_lit) != 0L) {
+                               pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0));
+                               if (!pic16_sameRegs(AOP(left), AOP(result)) )
+                                       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
+                               pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0));
+                       }
+               } else {
+                       unsigned long lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
+                       size = pic16_getDataSize(result);
+                       while (size--) {
+                               pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
+                               pic16_emitpcode (POC_MOVLW, pic16_popGetLit ((lit >> (8*offset)) & 0xFF));
+                               pic16_emitpcode (POC_ADDWFC, pic16_popGet(AOP(result), offset++));
+                               //MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));  
+                               //pic16_emitcode("addc","a,#00  ;%d",__LINE__);
+                               //pic16_aopPut(AOP(result),"a",offset++);
+                       }
+               }
+       goto release ;
+       } // left == CRY
+
+       /* if I can do an increment instead
+       of add then GOOD for ME */
+       if (pic16_genPlusIncr (ic) == TRUE)
+               goto release;   
+
+       size = pic16_getDataSize(result);
+
+       if(AOP(right)->type == AOP_LIT) {
+               /* Add a literal to something else */
+               //bool know_W=0;
+               unsigned lit = (unsigned) floatFromVal(AOP(right)->aopu.aop_lit);
+               //unsigned l1=0;
+
+               //offset = 0;
+               DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
+
+               genAddLit (ic,  lit);
+               goto release;
+
+       } else if(AOP_TYPE(right) == AOP_CRY) {
+
+               pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
+               pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
+               pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
+
+               /* here we are adding a bit to a char or int */
+               if(size == 1) {
+                       if (pic16_sameRegs(AOP(left), AOP(result)) ) {
+
+                               pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
+                               pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(result),0));
+
+                               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                               AOP(right)->aopu.aop_dir,
+                                               AOP(right)->aopu.aop_dir);
+                               pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(result),0,FALSE,FALSE));
+                       } else { // not same
+
+                               if(AOP_TYPE(left) == AOP_ACC) {
+                                       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
+                                       pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
+
+                                       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                       AOP(right)->aopu.aop_dir,
+                                       AOP(right)->aopu.aop_dir);
+                                       pic16_emitcode(" xorlw","1");
+                               } else {
+                                       pic16_mov2w(AOP(left),0);
+                                       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
+                                       pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(left),0));
+
+                                       pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
+                                       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                       AOP(right)->aopu.aop_dir,
+                                       AOP(right)->aopu.aop_dir);
+                                       pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
+                               }
+         
+                               if(AOP_TYPE(result) != AOP_ACC) {
+           
+                                       if(AOP_TYPE(result) == AOP_CRY) {
+                                               pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
+                                               pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(result),0));
+                                               emitSKPZ;
+                                               pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(result),0));
+                                       } else {
+                                               pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(result),0));
+                                               pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE));
+                                       }
+                               }
+                       }
+
+               } else {
+                       int offset = 1;
+                       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+                       if (pic16_sameRegs(AOP(left), AOP(result)) ) {
+                               emitCLRZ;
+                               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
+                               pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(result),0));
+
+                               pic16_emitcode("clrz","");
+
+                               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                               AOP(right)->aopu.aop_dir,
+                                               AOP(right)->aopu.aop_dir);
+                               pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(result),0,FALSE,FALSE));
+
+                       } else {
+                               emitCLRZ; // needed here as well: INCFW is not always executed, Z is undefined then
+                               pic16_mov2w(AOP(left),0);
+                               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
+                               pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
+                               //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right),0,FALSE,FALSE));
+                               emitMOVWF(right,0);
+
+                               pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
+                               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                               AOP(right)->aopu.aop_dir,
+                                               AOP(right)->aopu.aop_dir);
+                               pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
+                               pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE));
+
+                       }
+
+                       while(--size){
+                               emitSKPZ;
+                               pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(result),offset++));
+                               //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(right),offset++,FALSE,FALSE));
+                       }
+
+               }
       
-      if(sign)
-       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-      else
-       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-      offset++;
-    }
-  }
-
+       } else {
+               // add bytes
+
+               // Note: the following is an example of WISC code, eg.
+               // it's supposed to run on a Weird Instruction Set Computer :o)
+
+               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
+
+               if ( AOP_TYPE(left) == AOP_ACC) {
+                       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
+                       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),0));
+                       if ( AOP_TYPE(result) != AOP_ACC)
+                               pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
+                       goto release; // we're done, since WREG is 1 byte
+               }
+
+
+               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
+
+               size = min( AOP_SIZE(result), AOP_SIZE(right) );
+               size = min( size, AOP_SIZE(left) );
+               offset = 0;
+
+               if(pic16_debug_verbose) {
+//                     fprintf(stderr, "%s:%d result: %d\tleft: %d\tright: %d\n", __FILE__, __LINE__,
+//                             AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
+//                     fprintf(stderr, "%s:%d size of operands: %d\n", __FILE__, __LINE__, size);
+               }
+
+
+
+               if ((AOP_TYPE(left) == AOP_PCODE) && (
+                               (AOP(left)->aopu.pcop->type == PO_LITERAL) || 
+//                             (AOP(left)->aopu.pcop->type == PO_DIR) ||   // patch 9
+                               (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)))
+               {
+                       // add to literal operand
+
+                       // add first bytes
+                       for(i=0; i<size; i++) {
+                               if (AOP_TYPE(right) == AOP_ACC) {
+                                       pic16_emitpcode(POC_ADDLW, pic16_popGet(AOP(left),i));
+                               } else {
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+                                       if(i) { // add with carry
+                                               pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(right),i));
+                                       } else { // add without
+                                               pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),i));
+                                       }
+                               }
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+                       }
+                       
+                       DEBUGpic16_pic16_AopTypeSign(__LINE__, NULL, right, NULL);
+
+                       // add leftover bytes
+                       if (SPEC_USIGN(getSpec(operandType(right)))) {
+                               // right is unsigned
+                               for(i=size; i< AOP_SIZE(result); i++) {
+                                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+                                       pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+                               }
+
+                       } else {
+                               // right is signed, oh dear ...
+                               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_SETF, pic16_popGet(AOP(result),i));
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+                                       pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+                               }
+
+                       }
+                       goto release;
+
+               } else {
+                       // add regs
+
+                       // add first bytes
+                       for(i=0; i<size; i++) {
+                               if (AOP_TYPE(right) != AOP_ACC)
+                                 pic16_mov2w(AOP(right),i);
+                               if (pic16_sameRegs(AOP(left), AOP(result)))
+                               {
+                                       if(i) { // add with carry
+                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
+                                       } else { // add without
+                                               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),i));
+                                       }
+                               } else { // not same
+                                       if(i) { // add with carry
+                                               pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
+                                       } else { // add without
+                                               pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),i));
+                                       }
+                                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+                               }
+                       }
+
+                       // add leftover bytes
+                       // either left or right is too short
+                       for (i=size; i < AOP_SIZE(result); i++) {
+                         // get right operand into WREG
+                         if (i < AOP_SIZE(right)) {
+                           pic16_mov2w (AOP(right), i);
+                         } else {
+                           // right is too short
+                           pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
+                           if (!SPEC_USIGN(getSpec(operandType(right)))) {
+                             // 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_SETF, pic16_popCopyReg (&pic16_pc_wreg));
+                           }
+                         }
+
+                         // get left+WREG+CARRY into result
+                         if (i < AOP_SIZE(left)) {
+                           if (pic16_sameRegs (AOP(left), AOP(result))) {
+                             pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
+                           } else {
+                             pic16_emitpcode (POC_ADDFWC, pic16_popGet (AOP(left), i));
+                             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+                           }
+                         } else {
+                           // left is too short
+                           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
+                           if (!SPEC_USIGN(getSpec(operandType(left)))) {
+                             // 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_SETF, pic16_popGet (AOP(result), i));
+                           }
+                           pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
+                         }
+                       } // for i
+                       goto release;
+               }
 
-  //adjustArithmeticResult(ic);
+       }
 
- release:
-  pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-  pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-  pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+       assert( 0 );
+       
+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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1081,7 +1433,7 @@ bool pic16_genMinusDec (iCode *ic)
     unsigned int icount ;
     unsigned int size = pic16_getDataSize(IC_RESULT(ic));
 
-    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    FENTRY;
     /* will try to generate an increment */
     /* if the right side is not a literal 
     we cannot */
@@ -1104,8 +1456,7 @@ bool pic16_genMinusDec (iCode *ic)
 
       if(size == 2) { 
        pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),LSB));
-       pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(IC_RESULT(ic)),LSB));
-       pic16_emitpcode(POC_INCF,    pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
+       emitSKPC;
        pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
 
        pic16_emitcode("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
@@ -1113,27 +1464,24 @@ bool pic16_genMinusDec (iCode *ic)
        pic16_emitcode(" decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
       } else {
        /* size is 3 or 4 */
-       pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xff));
-       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),LSB));
-       emitSKPNC;
-       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
-       emitSKPNC;
-       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),MSB24));
+       pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(IC_RESULT(ic)),LSB));
+       pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_wreg));
+       pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
+       pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB24));
 
        pic16_emitcode("movlw","0xff");
        pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
 
-       emitSKPNC;
+       //emitSKPNC;
        pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
-       emitSKPNC;
+       //emitSKPNC;
        pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
 
        if(size > 3) {
-         emitSKPNC;
-         pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_RESULT(ic)),MSB32));
+         pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB32));
 
          pic16_emitcode("skpnc","");
-         emitSKPNC;
+         //emitSKPNC;
          pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
        }
 
@@ -1191,15 +1539,15 @@ 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));
-       pic16_emitpcode(POC_DECF, 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_SETF, pic16_popGet(AOP(result),offset));
       } else {
 
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
-       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
        while(size--)
-         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size));
 
       }
     } else
@@ -1214,7 +1562,8 @@ void pic16_addSign(operand *result, int offset, int sign)
 void pic16_genMinusBits (iCode *ic)
 {
     symbol *lbl = newiTempLabel(NULL);
-    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+    FENTRY;
     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
         pic16_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
         pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
@@ -1241,7 +1590,7 @@ void pic16_genMinus (iCode *ic)
   int size, offset = 0, same=0;
   unsigned long lit = 0L;
 
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    FENTRY;
   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
   pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
@@ -1268,8 +1617,8 @@ void pic16_genMinus (iCode *ic)
 
   /* if I can do an decrement instead
      of subtract then GOOD for ME */
-  //  if (pic16_genMinusDec (ic) == TRUE)
-  //    goto release;   
+//  if (pic16_genMinusDec (ic) == TRUE)
+//    goto release;   
 
   size = pic16_getDataSize(IC_RESULT(ic));   
   same = pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
@@ -1350,7 +1699,7 @@ void pic16_genMinus (iCode *ic)
          if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
            if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
              if(lit & 1) {
-               pic16_emitpcode(POC_MOVLW , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+               pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1));
                pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0));
              }
            }else{
@@ -1366,12 +1715,12 @@ void pic16_genMinus (iCode *ic)
            pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff));
            pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
            pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff));
-           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
+           //pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
 
          }
 
        } else {
-         pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+         pic16_mov2w(AOP(IC_LEFT(ic)),0);
          pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
          pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
        }
@@ -1406,8 +1755,7 @@ void pic16_genMinus (iCode *ic)
     if( (size == 1) && ((lit & 0xff) == 0) ) {
       /* res = 0 - right */
       if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
-       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       pic16_emitpcode(POC_NEGF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
       } else { 
        pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
        pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
@@ -1416,66 +1764,23 @@ void pic16_genMinus (iCode *ic)
       goto release;
     }
 
-    pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
+    pic16_mov2w(AOP(IC_RIGHT(ic)),0);
     pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));    
     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
 
 
-    offset = 1;
+    offset = 0;
     while(--size) {
       lit >>= 8;
-
-      if(size == 1) {
-       /* This is the last byte in a multibyte subtraction 
-        * There are a couple of tricks we can do by not worrying about 
-        * propogating the carry */
-       if(lit == 0xff) {
-         /* 0xff - x == ~x */
-         if(same) {
-           pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-           emitSKPC;
-           pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-         } else {
-           pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-           emitSKPC;
-           pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-         }
-       } else {
-           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-           emitSKPC;
-           pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-           pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));
-           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-       }
-
-       goto release;
-      }
-
+      offset++;
       if(same) {
-
-       if(lit & 0xff) {
-         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
-         emitSKPC;
-         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & 0xff)-1));
-         pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-       } else {
-         emitSKPNC;
-         pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-       }
+       // here we have x = lit - x   for sizeof(x)>1
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+       pic16_emitpcode(POC_SUBFWB_D1,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
       } else {
-
-       if(lit & 0xff) {
-         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
-         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-       } else
-         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-       emitSKPC;
-       pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-       pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
+       pic16_emitpcode(POC_SUBFWB_D0,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
+       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
       }
     }
   
@@ -1487,23 +1792,17 @@ void pic16_genMinus (iCode *ic)
                   pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
                   pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
 
-    if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
+    if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
       pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
-      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
+       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
     } else {
 
-      if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
-       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
-         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-      } else {
-
        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) 
-         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0));
+         pic16_mov2w(AOP(IC_RIGHT(ic)),0);
 
        if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
          pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
@@ -1523,7 +1822,6 @@ void pic16_genMinus (iCode *ic)
              pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
          }
        }
-      }
     }
 
     /*
@@ -1540,15 +1838,33 @@ void pic16_genMinus (iCode *ic)
     size--;
 
     while(size--){
-      if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
-       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+      if (offset < AOP_SIZE(IC_RIGHT(ic)))
+       pic16_mov2w(AOP(IC_RIGHT(ic)),offset);
+      else {
+       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
+       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_SETF, pic16_popCopyReg (&pic16_pc_wreg));
+       }
       }
-      pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-      emitSKPC;
-      pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-      pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
+      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+       pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+      } else {
+       if (offset < AOP_SIZE(IC_LEFT(ic))) {
+         pic16_emitpcode(POC_SUBWFB_D0,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
+         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+       } else {
+         // zero extend the left operand
+         pic16_emitpcode (POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
+         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_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));
+       }
+      }        
       offset++;
     }
 
@@ -1562,362 +1878,673 @@ void pic16_genMinus (iCode *ic)
   pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
 }
+
+
 /*-----------------------------------------------------------------*
- * pic_genUMult8XLit_16 - unsigned multiplication of two 8-bit numbers.
+ * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8XLit_16 (operand *left,
+void pic16_genUMult8XLit_8 (operand *left,
                             operand *right,
-                            operand *result,
-                            pCodeOpReg *result_hi)
-
+                            operand *result)
 {
-
   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__);
-    exit(1);
-  }
-
-
-  if(!result_hi) {
-    result_hi = PCOR(pic16_popGet(AOP(result),1));
-  }
-
-  lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
-  lit &= 0xff;
-  pic16_emitcode(";","Unrolled 8 X 8 multiplication");
-
-  same = pic16_sameRegs(AOP(left), AOP(result));
-
-  if(same) {
-    switch(lit) {
-    case 0:
-      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(left),0));
-      return;
-    case 2:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 3:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 4:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 5:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
-      return;
-    case 6:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 7:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 7*F
-      return;
-    case 8:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 8*F
-      return;
-    case 9:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 10:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 11:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 8*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 11*F
-      return;
-    case 12:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 13:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 8*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 13*F
-      return;
-    case 14:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 8*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 11*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 14*F
-      return;
-    case 15:
-      temp = pic16_popGetTempReg();
-      if(!temp) {
-       fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__);
-       exit(1);
-      }
-      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVWF,  temp);
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_SWAPFW, temp);
-      pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(left),0));
-      pic16_popReleaseTempReg(temp);
-      return;
-    case 16:
-      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 17:
-      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
-      pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 32:
-      pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xe0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 64:
-      pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xc0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 128:
-      pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(left),0));
-      return;
-
-    }
-  } else {
-
-    switch(lit) {
-    case 0:
-      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-      return;
-    case 2:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RLCF,  pic16_popCopyReg(result_hi));
-      return;
-    }
+  int size = AOP_SIZE(result);
+  int i;
 
-  }
+    FENTRY;
+       DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
 
-  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-  pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-  pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+       if (AOP_TYPE(right) != AOP_LIT){
+               fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+               exit(1);
+       }
 
-  have_first_bit = 0;
-  for(i=0; i<8; i++) {
+       lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
+       lit &= 0xff;
+       pic16_emitpcomment("Unrolled 8 X 8 multiplication");
+       pic16_emitpcomment("FIXME: the function does not support result==WREG");
+       
+       same = pic16_sameRegs(AOP(left), AOP(result));
+       if(same) {
+               switch(lit) {
+                       case 0:
+                               while (size--) {
+                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
+                               } // while
+                               return;
+                       case 2:
+                               // its faster to left shift
+                               for (i=1; i < size; i++) {
+                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
+                               } // for
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+                               if (size > 1)
+                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
+                               return;
+
+                       default:
+                               if(AOP_TYPE(left) != AOP_ACC)
+                                       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
+                                       pic16_popGet(AOP(result), 0)));
+                               if (size > 1) {
+                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
+                                                                           pic16_popGet(AOP(result), 1)));
+                                 for (i=2; i < size; i++) {
+                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
+                                 } // for
+                               } // if
+                               return;
+               }
+       } else {
+               // operands different
+               switch(lit) {
+                       case 0:
+                               while (size--) {
+                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
+                               } // while
+                               return;
+                       case 2:
+                               for (i=1; i < size; i++) {
+                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
+                               } // for
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+                               if (size > 1)
+                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
+                               return;
+                       default:
+                               if(AOP_TYPE(left) != AOP_ACC)
+                                       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
+                                       pic16_popGet(AOP(result), 0)));
+
+                               if (size > 1) {
+                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
+                                                                           pic16_popGet(AOP(result), 1)));
+                                 for (i=2; i < size; i++) {
+                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
+                                 } // for
+                               } // if
+                               return;
+               }
+       }
+}
 
-    if(lit & 1) {
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
-      have_first_bit = 1;
-    }
+/*-----------------------------------------------------------------------*
+ * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
+ *-----------------------------------------------------------------------*/
+void pic16_genUMult16XLit_16 (operand *left,
+                            operand *right,
+                            operand *result)
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
+  unsigned int lit;
+  int same;
 
-    if(have_first_bit) {
-      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
-    }
 
-    lit >>= 1;
-  }
+    FENTRY;
+    
+       if (AOP_TYPE(right) != AOP_LIT){
+               fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+               exit(1);
+       }
 
+       lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
+       lit &= 0xffff;
+
+       same = pic16_sameRegs(AOP(left), AOP(result));
+       if(same) {
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
+                               return;
+                       case 2:
+                               // its faster to left shift
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
+                               return;
+
+                       default: {
+                               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+                               pct1 = pic16_popGetTempReg(1);
+                               pct2 = pic16_popGetTempReg(1);
+                               pct3 = pic16_popGetTempReg(1);
+                               pct4 = pic16_popGetTempReg(1);
+
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+                               /* load result */
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pct1, pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
+                               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+                               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+                               pic16_popReleaseTempReg(pct4,1);
+                               pic16_popReleaseTempReg(pct3,1);
+                               pic16_popReleaseTempReg(pct2,1);
+                               pic16_popReleaseTempReg(pct1,1);
+                       }; return;
+               }
+       } else {
+               // operands different
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+                               return;
+                       case 2:
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+                               return;
+                       default: {
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+
+                       }; return;
+               }
+       }
 }
 
+
 /*-----------------------------------------------------------------*
- * genUMult8X8_16 - unsigned multiplication of two 8-bit numbers.
+ * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8X8_16 (operand *left,
+void pic16_genUMult8X8_8 (operand *left,
                           operand *right,
-                          operand *result,
-                          pCodeOpReg *result_hi)
+                          operand *result)
 
 {
+  FENTRY;
+  
 
-  int i;
-  int looped = 1;
-
-  if(!result_hi) {
-    result_hi = PCOR(pic16_popGet(AOP(result),1));
-  }
-
-  if (AOP_TYPE(right) == AOP_LIT) {
-    pic16_genUMult8XLit_16(left,right,result,result_hi);
-    return;
-  }
-
-  if(!looped) {
-    pic16_emitcode(";","Unrolled 8 X 8 multiplication");
-
-    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
-    pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-    pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-    emitCLRC;
+       if (AOP_TYPE(right) == AOP_LIT) {
+               pic16_genUMult8XLit_8(left,right,result);
+         return;
+       }
 
-    for(i=0; i<8; i++) {
-      pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),i,0));
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
-    }
+       /* cases:
+               A = A x B       B = A x B
+               A = B x C
+               W = A x B
+               W = W x B       W = B x W
+       */
+       /* if result == right then exchange left and right */
+       if(pic16_sameRegs(AOP(result), AOP(right))) {
+         operand *tmp;
+               tmp = left;
+               left = right;
+               right = tmp;
+       }
+               
+       if(AOP_TYPE(left) != AOP_ACC) {
+               // left is not WREG
+               if(AOP_TYPE(right) != AOP_ACC) {
+                       pic16_mov2w(AOP(left), 0);
+                       pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               } else {
+                       pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+               }
+       } else {
+               // left is WREG, right cannot be WREG (or can?!)
+               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0));
+       }
+       
+       /* result is in PRODL:PRODH */
+       if(AOP_TYPE(result) != AOP_ACC) {
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
+                       pic16_popGet(AOP(result), 0)));
 
 
-    /*
-      Here's another version that does the same thing and takes the 
-      same number of instructions. The one above is slightly better
-      because the entry instructions have a higher probability of
-      being optimized out.
-    */
-    /*
-      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+               if(AOP_SIZE(result)>1) {
+                 int i;
 
-      for(i=0; i<8; i++) {
-      emitSKPNC;
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
-      }
-    */
-
-  } else {
-    symbol  *tlbl = newiTempLabel(NULL);
-    pCodeOp *temp;
+                       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
+                       pic16_popGet(AOP(result), 1)));
+                       
+                       for(i=2;i<AOP_SIZE(result);i++)
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
+               }
+       } else {
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+       }
+}
 
+/*------------------------------------------------------------------*
+ * genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
+ *------------------------------------------------------------------*/
+void pic16_genUMult16X16_16 (operand *left,
+                          operand *right,
+                          operand *result)
 
-    pic16_emitcode(";","Looped 8 X 8 multiplication");
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
 
-    pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-    pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+    FENTRY;
 
-    pic16_emitpcode(POC_BSF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),0,FALSE,FALSE),7,0));
 
-    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+       if (AOP_TYPE(right) == AOP_LIT) {
+               pic16_genUMult8XLit_8(left,right,result);
+         return;
+       }
 
-    temp = pic16_popGetTempReg();
-    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(PCOR(temp)));
+       /* cases:
+               A = A x B       B = A x B
+               A = B x C
+       */
+       /* if result == right then exchange left and right */
+       if(pic16_sameRegs(AOP(result), AOP(right))) {
+         operand *tmp;
+               tmp = left;
+               left = right;
+               right = tmp;
+       }
 
-    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
 
-    pic16_emitpLabel(tlbl->key);
+       if(pic16_sameRegs(AOP(result), AOP(left))) {
+
+               pct1 = pic16_popGetTempReg(1);
+               pct2 = pic16_popGetTempReg(1);
+               pct3 = pic16_popGetTempReg(1);
+               pct4 = pic16_popGetTempReg(1);
+
+               pic16_mov2w(AOP(left), 0);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+               
+               pic16_mov2w(AOP(left), 1);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+               /* load result */
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
+               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+               pic16_popReleaseTempReg( pct4, 1 );
+               pic16_popReleaseTempReg( pct3, 1 );
+               pic16_popReleaseTempReg( pct2, 1 );
+               pic16_popReleaseTempReg( pct1, 1 );
 
-    pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(PCOR(temp)));
-    emitSKPNC;
-    pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
+       } else {
 
-    pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-    pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
+               pic16_mov2w(AOP(left), 0);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+               
+               pic16_mov2w(AOP(left), 1);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+       }       
+}
 
-    emitSKPC;
-    pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl->key));
 
-    pic16_popReleaseTempReg(temp);
+void pic16_genSMult16X16_16(operand *left,
+                       operand *right,
+                       operand *result)
+{
 
-  }
 }
 
+#if 0
 /*-----------------------------------------------------------------*
  * pic16_genSMult8X8_16 - signed multiplication of two 8-bit numbers
  *
  *  this routine will call the unsigned multiply routine and then
  * post-fix the sign bit.
  *-----------------------------------------------------------------*/
-void pic16_genSMult8X8_16 (operand *left,
+void pic16_genSMult8X8_8 (operand *left,
                           operand *right,
                           operand *result,
                           pCodeOpReg *result_hi)
 {
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
 
   if(!result_hi) {
     result_hi = PCOR(pic16_popGet(AOP(result),1));
   }
 
-  pic16_genUMult8X8_16(left,right,result,result_hi);
 
-  pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0));
+  pic16_genUMult8X8_8(left,right,result);
+
+  
+#if 0
+  pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0, PO_GPR_REGISTER));
   pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(result_hi));
-  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-  pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0));
+  pic16_mov2w(AOP(left),0);
+  pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0, PO_GPR_REGISTER));
   pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result),1));
-  
+#endif
 }
+#endif
 
 /*-----------------------------------------------------------------*
- * pic16_genMult8X8_8 - multiplication of two 8-bit numbers
- *
- *  this routine will call the unsigned multiply 8X8=>16 routine and
- * then throw away the high byte of the result.
- *
+ * pic16_genMult8X8_8 - multiplication of two 8-bit numbers        *
  *-----------------------------------------------------------------*/
 void pic16_genMult8X8_8 (operand *left,
                         operand *right,
                         operand *result)
 {
-  pCodeOp *result_hi = pic16_popGetTempReg();
+  FENTRY;
+  
+  if(AOP_TYPE(right) == AOP_LIT)
+    pic16_genUMult8XLit_8(left,right,result);
+  else
+    pic16_genUMult8X8_8(left,right,result);
+}
+
 
+/*-----------------------------------------------------------------*
+ * pic16_genMult16X16_16 - multiplication of two 16-bit numbers    *
+ *-----------------------------------------------------------------*/
+void pic16_genMult16X16_16 (operand *left,
+                        operand *right,
+                        operand *result)
+{
+  FENTRY;
+  
   if (AOP_TYPE(right) == AOP_LIT)
-    pic16_genUMult8XLit_16(left,right,result,PCOR(result_hi));
+    pic16_genUMult16XLit_16(left,right,result);
   else
-    pic16_genUMult8X8_16(left,right,result,PCOR(result_hi));
+    pic16_genUMult16X16_16(left,right,result);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*
+ * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
+ *-----------------------------------------------------------------------*/
+void pic16_genUMult32XLit_32 (operand *left,
+                            operand *right,
+                            operand *result)
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
+  unsigned int lit;
+  int same;
+
+
+    FENTRY;
+    
+       if (AOP_TYPE(right) != AOP_LIT){
+               fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+               exit(1);
+       }
 
-  pic16_popReleaseTempReg(result_hi);
+       lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
+       lit &= 0xffff;
+
+       same = pic16_sameRegs(AOP(left), AOP(result));
+       if(same) {
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
+                               return;
+                       case 2:
+                               // its faster to left shift
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
+                               return;
+
+                       default: {
+                               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+                               pct1 = pic16_popGetTempReg(1);
+                               pct2 = pic16_popGetTempReg(1);
+                               pct3 = pic16_popGetTempReg(1);
+                               pct4 = pic16_popGetTempReg(1);
+
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+                               /* load result */
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pct1, pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
+                               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+                               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+                               pic16_popReleaseTempReg( pct4, 1 );
+                               pic16_popReleaseTempReg( pct3, 1 );
+                               pic16_popReleaseTempReg( pct2, 1 );
+                               pic16_popReleaseTempReg( pct1, 1 );
+                       }; return;
+               }
+       } else {
+               // operands different
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+                               return;
+                       case 2:
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+                               return;
+                       default: {
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+
+                       }; return;
+               }
+       }
 }
+
+
+/*------------------------------------------------------------------*
+ * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
+ *------------------------------------------------------------------*/
+void pic16_genUMult32X32_32 (operand *left,
+                          operand *right,
+                          operand *result)
+
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
+
+    FENTRY;
+    
+       if (AOP_TYPE(right) == AOP_LIT) {
+               pic16_genUMult8XLit_8(left,right,result);
+         return;
+       }
+
+       /* cases:
+               A = A x B       B = A x B
+               A = B x C
+       */
+       /* if result == right then exchange left and right */
+       if(pic16_sameRegs(AOP(result), AOP(right))) {
+         operand *tmp;
+               tmp = left;
+               left = right;
+               right = tmp;
+       }
+
+
+       if(pic16_sameRegs(AOP(result), AOP(left))) {
+
+               pct1 = pic16_popGetTempReg(1);
+               pct2 = pic16_popGetTempReg(1);
+               pct3 = pic16_popGetTempReg(1);
+               pct4 = pic16_popGetTempReg(1);
+
+               pic16_mov2w(AOP(left), 0);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+               
+               pic16_mov2w(AOP(left), 1);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+               /* load result */
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
+               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+               pic16_popReleaseTempReg( pct4, 1 );
+               pic16_popReleaseTempReg( pct3, 1 );
+               pic16_popReleaseTempReg( pct2, 1 );
+               pic16_popReleaseTempReg( pct1, 1 );
+
+       } else {
+
+               pic16_mov2w(AOP(left), 0);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+               
+               pic16_mov2w(AOP(left), 1);
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+       }       
+}
+
+
+/*-----------------------------------------------------------------*
+ * pic16_genMult32X32_32 - multiplication of two 32-bit numbers    *
+ *-----------------------------------------------------------------*/
+void pic16_genMult32X32_32 (operand *left,
+                        operand *right,
+                        operand *result)
+{
+  FENTRY;
+  
+  if (AOP_TYPE(right) == AOP_LIT)
+    pic16_genUMult32XLit_32(left,right,result);
+  else
+    pic16_genUMult32X32_32(left,right,result);
+}
+
+
+
+
+
+
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* constMult - generates code for multiplication by a constant     */