* src/pic16/glue.c (pic16_initPointer): avoid assertion, emit better
[fw/sdcc] / src / pic16 / genarith.c
index 81ef668107f2113b171fb7fc35890e9ad3eba339..68fdf921a77726cb367b5ed71776a23c92d033ae 100644 (file)
 #include "pcode.h"
 #include "gen.h"
 
-//#define D_POS(txt) DEBUGpic16_emitcode ("; TECODEV::: " txt, " (%s:%d (%s))", __FILE__, __LINE__, __FUNCTION__)
-
-#define D_POS(msg)     DEBUGpic16_emitcode("; ", msg, "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__)
-
 #if 1
 #define pic16_emitcode DEBUGpic16_emitcode
 #endif
@@ -117,6 +113,7 @@ const char *pic16_pCodeOpType(pCodeOp *pcop)
     case PO_STR:               return  "PO_STR";
     case PO_LABEL:             return  "PO_LABEL";
     case PO_WILD:              return  "PO_WILD";
+    case PO_TWO_OPS:           return  "PO_TWO_OPS";
     }
   }
 
@@ -156,6 +153,7 @@ const char *pic16_pCodeOpSubType(pCodeOp *pcop)
     case PO_STR:               return  "PO_STR";
     case PO_LABEL:             return  "PO_LABEL";
     case PO_WILD:              return  "PO_WILD";
+    case PO_TWO_OPS:           return  "PO_TWO_OPS";
     }
   }
 
@@ -167,10 +165,11 @@ const char *pic16_pCodeOpSubType(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))),
@@ -206,7 +205,7 @@ 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( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) &&
        (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
@@ -280,8 +279,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))),
@@ -420,12 +418,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;
@@ -441,6 +441,7 @@ static void genAddLit2byte (operand *result, int offr, int lit)
   }
 
 }
+#endif
 
 static void emitMOVWF(operand *reg, int offset)
 {
@@ -456,6 +457,9 @@ static void emitMOVWF(operand *reg, int offset)
 
 }
 
+
+#if 1
+
 static void genAddLit (iCode *ic, int lit)
 {
 
@@ -465,7 +469,7 @@ static void genAddLit (iCode *ic, int lit)
   operand *result;
   operand *left;
 
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    FENTRY;
 
 
   left = IC_LEFT(ic);
@@ -532,7 +536,6 @@ static void genAddLit (iCode *ic, int lit)
          pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
          break;
        default: /* 0x01LL */
-         D_POS("FIXED: added default case for adding 0x01??");
          pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
          pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
          emitSKPNC;
@@ -577,11 +580,9 @@ static void genAddLit (iCode *ic, int lit)
          genAddLit2byte (result, MSB16, hi);
          break;
        case 1:  /* 0xHH01 */
-         D_POS(">>> IMPROVED");
          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));
-         D_POS("<<< IMPROVED");
          break;
 /*     case 0xff: * 0xHHff *
          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
@@ -593,9 +594,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));
-         D_POS(">>> IMPROVED");
          pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
-         D_POS("<<< IMPROVED");
          break;
        }
 
@@ -610,26 +609,339 @@ static void genAddLit (iCode *ic, int lit)
        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:
-           D_POS(">>> IMPROVED and compacted");
-           emitSKPNC;
+           break;
+         case 1:
            pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
-           D_POS("<<< IMPROVED and compacted");
+           carry_info=1;
            break;
-         case 0xff:
+         default:
            pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
-           D_POS(">>> Changed from SKPZ/SKPC to always SKPC");
-           emitSKPC;
            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;
-         default:
-           D_POS(">>> IMPROVED and compacted");
+         }
+       }
+       offset++;
+       lit >>= 8;
+      }
+    
+/*
+      lo = BYTEofLONG(lit,0);
+
+      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_ADDWFC, pic16_popGet(AOP(result),offset));
-           D_POS("<<< IMPROVED and compacted");
-           break;
+           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 {
+    int offset = 1;
+    DEBUGpic16_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
+
+    if(size == 1) {
+
+      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 {
+       /* 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);
+       }
+      }
+
+    } else {
+      int clear_carry=0;
+
+      /* 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;
+       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));
+         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++;
+      }
+    }
+  }
+}
+
+#else
+    /* 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;
+
+  operand *result;
+  operand *left;
+
+    FENTRY;
+
+
+  left = IC_LEFT(ic);
+  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 */
+  pic16_addSign(result, sizeL, !IS_UNSIGNED(operandType(left)));
+
+  /* special cases */
+  if (lit == 0) {
+    /* nothing to do */
+  } else if (lit == 1) {
+    switch (size) {
+    case 1:
+      /* handled below */
+      break;
+    case 2:
+      pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(result), 0));
+      break;
+    default:
+      assert (size > 2);
+      pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), 0));
+      for (i=1; i < size-1; i++) {
+        emitSKPNC; /* a jump here saves up to 2(size-2)cycles */
+        pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), i));
+      } // for i
+      emitSKPNC;
+      break;
+    } // switch
+    
+    pic16_emitpcode (POC_INCF, pic16_popGet (AOP(result), size-1));
+  } else {
+    /* general case */
+
+    /* add literal to result */
+    for (i=0; i < size; i++) {
+      pic16_emitpcode (POC_MOVLW, pic16_popGetLit (llit));
+      llit >>= 8; /* FIXME: arithmetic right shift for signed literals? */
+      pic16_emitpcode (i == 0 ? POC_ADDWF : POC_ADDWFC,
+       pic16_popGet (AOP(result), i));
+    }
+  }
+
+#if 0
+
+  if(same) {
+
+    /* Handle special cases first */
+    if(size == 1) 
+      genAddLit2byte (result, 0, lit);
+     
+    else if(size == 2) {
+      int hi = 0xff & (lit >> 8);
+      lo = lit & 0xff;
+
+      switch(hi) {
+      case 0: 
+
+       /* 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));
+
+         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));
+
+
+       }
+       break;
+
+      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;
+
+      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));
+         
+       }
+
+       break;
+       
+      default:
+       DEBUGpic16_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
+
+       /* 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;
+       }
+
+      }
+    } else {
+      int carry_info = 0;
+      int offset = 0;
+      /* size > 2 */
+      DEBUGpic16_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
+
+      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 */
@@ -675,7 +987,6 @@ static void genAddLit (iCode *ic, int lit)
 
        } 
       } 
-    }
 
 */
     }
@@ -701,9 +1012,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);
-         D_POS(">>> REMOVED double assignment");
          break;
        case 1:
          pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
@@ -731,7 +1041,7 @@ 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;
       }
@@ -747,45 +1057,41 @@ static void genAddLit (iCode *ic, int lit)
 
            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
            pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(left),offset));
-           D_POS(">>> FIXED from left to result");
            pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
-           D_POS("<<< FIXED from left to result");
 
            clear_carry = 0;
 
          } else {
-           D_POS(">>> FIXED");
            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));
-           D_POS("<<< FIXED");
          }
 
        } else {
-         D_POS(">>> IMPROVED");
          pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
-         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
+         pic16_mov2w(AOP(left),offset);
          pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
-         D_POS("<<< IMPROVED");
        }
        offset++;
       }
     }
   }
+#endif
 }
 
+#endif
+
 /*-----------------------------------------------------------------*/
 /* pic16_genPlus - generates code for addition                     */
 /*-----------------------------------------------------------------*/
 void pic16_genPlus (iCode *ic)
 {
-       int i, size, offset = 0;
-       operand *result, *left, *right;
-
-       /* special cases :- */
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
+  int i, size, offset = 0;
+  operand *result, *left, *right;
 
+    FENTRY;
+    
+    /* special cases :- */
        result = IC_RESULT(ic);
        left = IC_LEFT(ic);
        right = IC_RIGHT(ic);
@@ -801,8 +1107,8 @@ void pic16_genPlus (iCode *ic)
 
        if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) {
                operand *t = right;
-               right = left;
-               left = t;
+               right = IC_RIGHT(ic) = left;
+               left = IC_LEFT(ic) = t;
        }
 
        /* if both left & right are in bit space */
@@ -824,11 +1130,15 @@ void pic16_genPlus (iCode *ic)
                                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--) {
-                               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));  
-                               pic16_emitcode("addc","a,#00  ;%d",__LINE__);
-                               pic16_aopPut(AOP(result),"a",offset++);
+                               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 ;
@@ -839,12 +1149,12 @@ void pic16_genPlus (iCode *ic)
        if (pic16_genPlusIncr (ic) == TRUE)
                goto release;   
 
-       size = pic16_getDataSize(IC_RESULT(ic));
+       size = pic16_getDataSize(result);
 
-       if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
+       if(AOP(right)->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 lit = (unsigned) floatFromVal(AOP(right)->aopu.aop_lit);
                //unsigned l1=0;
 
                //offset = 0;
@@ -853,55 +1163,55 @@ void pic16_genPlus (iCode *ic)
                genAddLit (ic,  lit);
                goto release;
 
-       } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+       } else if(AOP_TYPE(right) == AOP_CRY) {
 
-               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));
+               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(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+                       if (pic16_sameRegs(AOP(left), AOP(result)) ) {
 
-                               pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
-                               pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+                               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(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));
+                                               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(IC_LEFT(ic)) == AOP_ACC) {
-                                       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+                               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(IC_RIGHT(ic))->aopu.aop_dir,
-                                       AOP(IC_RIGHT(ic))->aopu.aop_dir);
+                                       AOP(right)->aopu.aop_dir,
+                                       AOP(right)->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));
+                                       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(IC_LEFT(ic)),0,FALSE,FALSE));
+                                       pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),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));
+                                       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(IC_RESULT(ic)) != AOP_ACC) {
+                               if(AOP_TYPE(result) != AOP_ACC) {
            
-                                       if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+                                       if(AOP_TYPE(result) == AOP_CRY) {
                                                pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
-                                               pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+                                               pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(result),0));
                                                emitSKPZ;
-                                               pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+                                               pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(result),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));
+                                               pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(result),0));
+                                               pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE));
                                        }
                                }
                        }
@@ -909,39 +1219,39 @@ void pic16_genPlus (iCode *ic)
                } else {
                        int offset = 1;
                        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-                       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+                       if (pic16_sameRegs(AOP(left), AOP(result)) ) {
                                emitCLRZ;
-                               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-                               pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+                               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(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));
+                                               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_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);
+                               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(IC_LEFT(ic)),0,FALSE,FALSE));
+                               pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),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));
+                                               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(IC_RESULT(ic)),offset++));
-                               //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
+                               pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(result),offset++));
+                               //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(right),offset++,FALSE,FALSE));
                        }
 
                }
@@ -998,6 +1308,8 @@ void pic16_genPlus (iCode *ic)
                                }
                                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)))) {
@@ -1012,10 +1324,8 @@ void pic16_genPlus (iCode *ic)
                                // right is signed, oh dear ...
                                for(i=size; i< AOP_SIZE(result); i++) {
                                        pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
-                                       D_POS(">>> FIXED sign test from result to right");
                                        pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                                       D_POS("<<< FIXED sign test from result to right");
-                                       pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i));
+                                       pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),i));
                                        pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
                                        pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
                                }
@@ -1029,7 +1339,7 @@ void pic16_genPlus (iCode *ic)
                        // add first bytes
                        for(i=0; i<size; i++) {
                                if (AOP_TYPE(right) != AOP_ACC)
-                                       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),i));
+                                 pic16_mov2w(AOP(right),i);
                                if (pic16_sameRegs(AOP(left), AOP(result)))
                                {
                                        if(i) { // add with carry
@@ -1048,99 +1358,51 @@ void pic16_genPlus (iCode *ic)
                        }
 
                        // add leftover bytes
-                       if (SPEC_USIGN(getSpec(operandType(right)))) {
-                               // right is unsigned
-                               for(i=size; i< AOP_SIZE(result); i++) {
-                                       if (pic16_sameRegs(AOP(left), AOP(result)))
-                                       {
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
-                                       } else { // not same
-                                               D_POS (">>> FIXED added to uninitialized result");
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
-                                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
-                                               D_POS ("<<< FIXED");
-                                       }
-                               }
-                       } else {
-                               // right is signed
-                               for(i=size; i< AOP_SIZE(result); i++) {
-                                       if(size < AOP_SIZE(left)) {
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                                               pic16_emitpcode(POC_COMFW, pic16_popCopyReg(&pic16_pc_wreg));
-                                               if (pic16_sameRegs(AOP(left), AOP(result)))
-                                               {
-                                                       pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
-                                               } else { // not same
-                                                       pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
-                                                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
-                                               }
-                                       } else {
-                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
-                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), i));
-                                       }
-                               }
-                       }
+                       // 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;
                }
 
        }
 
        assert( 0 );
-       // TODO:        anything from here to before "release:" is probably obsolete and should be removed
-       //              when the regression tests are stable
-
-       if (AOP_SIZE(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));
-
-
-               if(sign) {
-                       /* Now this is really horrid. Gotta check the sign of the addends and propogate
-                       * to the result */
-
-                       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                       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, PO_GPR_REGISTER));
-                       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-                       /* if chars or ints or being signed extended to longs: */
-                       if(size) {
-                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
-                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
-                       }
-               }
-
-               offset++;
-               while(size--) {
-      
-                       if(sign)
-                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-                       else
-                               pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-                       offset++;
-               }
-       }
-
-
-       //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);
+       
+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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1151,7 +1413,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 */
@@ -1174,8 +1436,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));
@@ -1183,27 +1444,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));
        }
 
@@ -1262,7 +1520,7 @@ void pic16_addSign(operand *result, int offset, int sign)
       if(size == 1) {
        pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
        pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
-       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
+       pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
       } else {
 
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
@@ -1284,7 +1542,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));
@@ -1299,7 +1558,7 @@ void pic16_genMinusBits (iCode *ic)
         pic16_emitcode("inc","a");
         pic16_emitcode("","%05d_DS_:",(lbl->key+100));
         pic16_aopPut(AOP(IC_RESULT(ic)),"a",0);
-        pic16_addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
+        pic16_addSign(IC_RESULT(ic), MSB16, !IS_UNSIGNED(operandType(IC_RESULT(ic))));
     }
 }
 
@@ -1311,7 +1570,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);
@@ -1420,7 +1679,6 @@ 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) {
-               D_POS(">>> FIXED from MOVLW right(=result) to MOVLW left(=literal,left&1==1)");
                pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1));
                pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0));
              }
@@ -1437,13 +1695,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));
-           D_POS(">>> IMPROVED removed following assignment W-->result");
            //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));
        }
@@ -1478,9 +1735,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))) ) {
-       D_POS(">>> IMPROVED changed comf,incf to negf");
        pic16_emitpcode(POC_NEGF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       D_POS("<<< IMPROVED changed comf,incf to negf");
       } else { 
        pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
        pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
@@ -1489,7 +1744,7 @@ 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));
 
@@ -1498,7 +1753,6 @@ void pic16_genMinus (iCode *ic)
     while(--size) {
       lit >>= 8;
       offset++;
-      D_POS(">>> FIXED and compacted");
       if(same) {
        // here we have x = lit - x   for sizeof(x)>1
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
@@ -1508,7 +1762,6 @@ void pic16_genMinus (iCode *ic)
        pic16_emitpcode(POC_SUBFWB_D0,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
        pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
       }
-      D_POS("<<< FIXED and compacted");
     }
   
 
@@ -1529,7 +1782,7 @@ void pic16_genMinus (iCode *ic)
 
        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));
@@ -1565,16 +1818,32 @@ void pic16_genMinus (iCode *ic)
     size--;
 
     while(size--){
+      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));
+       }
+      }
       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
-       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-       D_POS(">>> IMPROVED by replacing emitSKPC, incfszw by subwfb");
-       pic16_emitpcode(POC_SUBWFB_D1,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-       D_POS("<<< IMPROVED by replacing emitSKPC, incfszw by subwfb");
+       pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
       } else {
-       D_POS(">>> FIXED for same regs right and result");
-       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-       pic16_emitpcode(POC_SUBWFB_D0,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
-       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+       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++;
     }
@@ -1592,73 +1861,127 @@ void pic16_genMinus (iCode *ic)
 
 
 /*-----------------------------------------------------------------*
- * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
+ * pic_genMult8XLit_n - multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8XLit_8 (operand *left,
-                            operand *right,
-                            operand *result)
+void pic16_genMult8XLit_n (operand *left,
+    operand *right,
+    operand *result)
 {
-  unsigned int lit;
+  int lit;
   int same;
+  int size = AOP_SIZE(result);
+  int i;
 
+  FENTRY;
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
-  
-       if (AOP_TYPE(right) != AOP_LIT){
-               fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
-               exit(1);
-       }
+  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 &= 0xff;
-       pic16_emitpcomment("Unrolled 8 X 8 multiplication");
-       pic16_emitpcomment("FIXME: the function does not support result==WREG");
+  lit = (int)floatFromVal(AOP(right)->aopu.aop_lit);
+  assert( (lit >= -128) && (lit < 256) );
+  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 & 0x00ff) {
+      case 0:
+       while (size--) {
+         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
+       } // while
+       return;
        
-       same = pic16_sameRegs(AOP(left), AOP(result));
-       if(same) {
-               switch(lit) {
-                       case 0:
-                               pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-                               return;
-                       case 2:
-                               // its faster to left shift
-                               emitCLRC;
-                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
-                               return;
+      case 2:
+       /* sign extend left in result */
+       pic16_addSign(result, 1, !IS_UNSIGNED(operandType(left)));
+       // its faster to left shift
+       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)));
-                               return;
-               }
+      default:
+       if(AOP_TYPE(left) != AOP_ACC)
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+       pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit & 0x00ff));
+       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+               &pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+       /* Adjust result's high bytes below! */
+    }
+  } else {
+    // operands different
+    switch(lit & 0x00ff) {
+      case 0:
+       while (size--) {
+         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
+       } // while
+       return;
+       
+      case 2:
+       if (IS_UNSIGNED(operandType(result))) {
+         for (i=1; i < size; i++) {
+           pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
+         } // for
        } else {
-               // operands different
-               switch(lit) {
-                       case 0:
-                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
-                               return;
-                       case 2:
-                               emitCLRC;
-                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
-                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
-                               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)));
-                               return;
-               }
+         /* sign extend left to result */
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+         for (i=1; i < size; i++) {
+           pic16_emitpcode(POC_MOVWF,  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)));
+       /* Adjust result's high bytes below! */
+    }
+  }
+
+  if (size > 1) {
+    /* We need to fix PRODH for
+     * (a) literals < 0 and
+     * (b) signed register operands < 0.
+     */
+    //printf( "%s: lit %d, left unsigned: %d\n", __FUNCTION__, lit, SPEC_USIGN(getSpec(operandType(left))));
+    if (lit < 0) {
+      /* literal negative (i.e. in [-128..-1]), high byte == -1 */
+      pic16_mov2w(AOP(left), 0);
+      pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+    }
+
+    if (!SPEC_USIGN(getSpec(operandType(left)))) {
+      /* register operand signed, determine signedness of high byte */
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0x00ff));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+      pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+    }
+
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+           &pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+    /* Need to sign-extend here. */
+    pic16_addSign(result, 2, !IS_UNSIGNED(operandType(result)));
+  } // if
 }
 
+#if 0
 /*-----------------------------------------------------------------------*
  * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
  *-----------------------------------------------------------------------*/
@@ -1671,8 +1994,8 @@ void pic16_genUMult16XLit_16 (operand *left,
   int same;
 
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
+    FENTRY;
+    
        if (AOP_TYPE(right) != AOP_LIT){
                fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
                exit(1);
@@ -1771,73 +2094,101 @@ void pic16_genUMult16XLit_16 (operand *left,
                }
        }
 }
+#endif
 
 
 /*-----------------------------------------------------------------*
- * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
+ * genMult8X8_n - multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8X8_8 (operand *left,
-                          operand *right,
-                          operand *result)
+void pic16_genMult8X8_n (operand *left, operand *right, operand *result)
 
 {
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  FENTRY;
 
 
-       if (AOP_TYPE(right) == AOP_LIT) {
-               pic16_genUMult8XLit_8(left,right,result);
-         return;
-       }
+  if (AOP_TYPE(right) == AOP_LIT) {
+    pic16_genMult8XLit_n(left,right,result);
+    return;
+  }
 
-       /* 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_emitpcode(POC_MOVFW, pic16_popGet(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)));
+  /* 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));
+  }
 
-               if(AOP_SIZE(result)>1) {
-                 int i;
+  /* 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)));
+
+
+    if(AOP_SIZE(result)>1) {
+
+      /* If s8 x s8 --> s16 multiplication was called for, fixup high byte.
+       * (left=a1a0, right=b1b0, X1: high byte, X0: low byte)
+       * 
+       *    a1a0 * b1b0
+       * --------------
+       *      a1b0 a0b0
+       * a1b1 a0b1
+       * ---------------
+       *           a0b0  a1= 0, b1= 0 (both unsigned)
+       *       -b0 a0b0  a1=-1, b1= 0 (a signed and < 0, b unsigned or >= 0)
+       *       -a0 a0b0  a1= 0, b1=-1 (b signed and < 0, a unsigned or >= 0)
+       *  -(a0+b0) a0b0  a1=-1, b1=-1 (a and b signed and < 0)
+       *
+       *  Currently, PRODH:PRODL holds a0b0 as 16 bit value; we need to
+       *  subtract a0 and/or b0 from PRODH. */
+      if (!IS_UNSIGNED(operandType(right))) {
+       /* right operand (b1) signed and < 0, then subtract left op (a0) */
+       pic16_mov2w( AOP(left), 0 );
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+      }
 
-                       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));
-       }
+      if (!IS_UNSIGNED(getSpec(operandType(left)))) {
+       /* left operand (a1) signed and < 0, then subtract right op (b0) */
+       pic16_mov2w( AOP(right), 0 );
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+      }
+
+      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+             &pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+      /* Must sign-extend here. */
+      pic16_addSign(result, 2, !IS_UNSIGNED(operandType(left)));
+    }
+  } else {
+    pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+  }
 }
 
+#if 0
 /*------------------------------------------------------------------*
  * genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
  *------------------------------------------------------------------*/
@@ -1848,11 +2199,11 @@ void pic16_genUMult16X16_16 (operand *left,
 {
   pCodeOp *pct1, *pct2, *pct3, *pct4;
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    FENTRY;
 
 
        if (AOP_TYPE(right) == AOP_LIT) {
-               pic16_genUMult8XLit_8(left,right,result);
+               pic16_genMult8XLit_n(left,right,result);
          return;
        }
 
@@ -1876,7 +2227,7 @@ void pic16_genUMult16X16_16 (operand *left,
                pct3 = pic16_popGetTempReg(1);
                pct4 = pic16_popGetTempReg(1);
 
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 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_pCodeOpCopy(pct1)));
@@ -1888,7 +2239,7 @@ void pic16_genUMult16X16_16 (operand *left,
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
                        pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
                
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+               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)));
@@ -1908,7 +2259,7 @@ void pic16_genUMult16X16_16 (operand *left,
 
        } else {
 
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 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)));
@@ -1920,20 +2271,22 @@ void pic16_genUMult16X16_16 (operand *left,
                pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
                pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
                
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 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));
        }       
 }
+#endif
 
-
+#if 0
 void pic16_genSMult16X16_16(operand *left,
                        operand *right,
                        operand *result)
 {
 
 }
+#endif
 
 #if 0
 /*-----------------------------------------------------------------*
@@ -1961,7 +2314,7 @@ void pic16_genSMult8X8_8 (operand *left,
 #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_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
@@ -1975,15 +2328,16 @@ void pic16_genMult8X8_8 (operand *left,
                         operand *right,
                         operand *result)
 {
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
-       if(AOP_TYPE(right) == AOP_LIT)
-               pic16_genUMult8XLit_8(left,right,result);
-       else
-               pic16_genUMult8X8_8(left,right,result);
+  FENTRY;
+  
+  if(AOP_TYPE(right) == AOP_LIT)
+    pic16_genMult8XLit_n(left,right,result);
+  else
+    pic16_genMult8X8_n(left,right,result);
 }
 
 
+#if 0
 /*-----------------------------------------------------------------*
  * pic16_genMult16X16_16 - multiplication of two 16-bit numbers    *
  *-----------------------------------------------------------------*/
@@ -1991,18 +2345,17 @@ void pic16_genMult16X16_16 (operand *left,
                         operand *right,
                         operand *result)
 {
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
-       if (AOP_TYPE(right) == AOP_LIT)
-               pic16_genUMult16XLit_16(left,right,result);
-       else
-               pic16_genUMult16X16_16(left,right,result);
-
+  FENTRY;
+  
+  if (AOP_TYPE(right) == AOP_LIT)
+    pic16_genUMult16XLit_16(left,right,result);
+  else
+    pic16_genUMult16X16_16(left,right,result);
 }
+#endif
 
 
-
-
+#if 0
 /*-----------------------------------------------------------------------*
  * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
  *-----------------------------------------------------------------------*/
@@ -2015,8 +2368,8 @@ void pic16_genUMult32XLit_32 (operand *left,
   int same;
 
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
+    FENTRY;
+    
        if (AOP_TYPE(right) != AOP_LIT){
                fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
                exit(1);
@@ -2115,8 +2468,9 @@ void pic16_genUMult32XLit_32 (operand *left,
                }
        }
 }
+#endif
 
-
+#if 0
 /*------------------------------------------------------------------*
  * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
  *------------------------------------------------------------------*/
@@ -2127,11 +2481,10 @@ void pic16_genUMult32X32_32 (operand *left,
 {
   pCodeOp *pct1, *pct2, *pct3, *pct4;
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
-
+    FENTRY;
+    
        if (AOP_TYPE(right) == AOP_LIT) {
-               pic16_genUMult8XLit_8(left,right,result);
+               pic16_genMult8XLit_n(left,right,result);
          return;
        }
 
@@ -2155,7 +2508,7 @@ void pic16_genUMult32X32_32 (operand *left,
                pct3 = pic16_popGetTempReg(1);
                pct4 = pic16_popGetTempReg(1);
 
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 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_pCodeOpCopy(pct1)));
@@ -2167,7 +2520,7 @@ void pic16_genUMult32X32_32 (operand *left,
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
                        pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
                
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+               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)));
@@ -2187,7 +2540,7 @@ void pic16_genUMult32X32_32 (operand *left,
 
        } else {
 
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 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)));
@@ -2199,14 +2552,16 @@ void pic16_genUMult32X32_32 (operand *left,
                pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
                pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
                
-               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 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));
        }       
 }
+#endif
 
 
+#if 0
 /*-----------------------------------------------------------------*
  * pic16_genMult32X32_32 - multiplication of two 32-bit numbers    *
  *-----------------------------------------------------------------*/
@@ -2214,14 +2569,14 @@ void pic16_genMult32X32_32 (operand *left,
                         operand *right,
                         operand *result)
 {
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-
-       if (AOP_TYPE(right) == AOP_LIT)
-               pic16_genUMult32XLit_32(left,right,result);
-       else
-               pic16_genUMult32X32_32(left,right,result);
-
+  FENTRY;
+  
+  if (AOP_TYPE(right) == AOP_LIT)
+    pic16_genUMult32XLit_32(left,right,result);
+  else
+    pic16_genUMult32X32_32(left,right,result);
 }
+#endif